Hubbry Logo
ALGOL 68ALGOL 68Main
Open search
ALGOL 68
Community hub
ALGOL 68
logo
7 pages, 0 posts
0 subscribers
Be the first to start a discussion here.
Be the first to start a discussion here.
ALGOL 68
ALGOL 68
from Wikipedia

ALGOL 68
Revised Report on the Algorithmic Language – Algol 68 Edited by: A. van Wijngaarden et al, September 1973[1]
ParadigmsMulti-paradigm: concurrent, imperative
FamilyALGOL
Designed byA. van Wijngaarden, B. J. Mailloux, J. E. L. Peck and C. H. A. Koster, et al.
First appearedFinal Report: 1968; 57 years ago (1968)r0
Stable release
Algol 68/RR / Revised Report: 1973; 52 years ago (1973)r1
Typing disciplinestatic, strong, safe, structural
ScopeLexical
Websitealgol68-lang.org
Major implementations
ALGOL 68C, Algol 68 Genie (recent), ALGOL 68-R, ALGOL 68RS, ALGOL 68S, FLACC, Алгол 68 Ленинград/Leningrad Unit, Odra ALGOL 68
Dialects
ALGOL 68/FR (Final Reportr0)
Influenced by
ALGOL 60, ALGOL Y
Influenced
C,[2][3] C++,[4] Bourne shell, KornShell, Bash, Steelman, Ada, Python,[5] Mary, S3

ALGOL 68 (short for Algorithmic Language 1968) is an imperative programming language member of the ALGOL family that was conceived as a successor to the ALGOL 60 language, designed with the goal of a much wider scope of application and more rigorously defined syntax and semantics.

The complexity of the language's definition, which runs to several hundred pages filled with non-standard terminology, made compiler implementation difficult and it was said it had "no implementations and no users". This was only partly true; ALGOL 68 did find use in several niche markets, notably in the United Kingdom where it was popular on International Computers Limited (ICL) machines, and in teaching roles. Outside these fields, use was relatively limited.

Nevertheless, the contributions of ALGOL 68 to the field of computer science have been deep, wide-ranging and enduring, although many of these contributions were only publicly identified when they had reappeared in subsequently developed programming languages. Many languages were developed specifically as a response to the perceived complexity of the language, the most notable being Pascal, or were reimplementations for specific roles, like Ada.

Many languages of the 1970s trace their design specifically to ALGOL 68, selecting some features while abandoning others that were considered too complex or out-of-scope for given roles. Most modern languages trace at least some of their syntax to either C or Pascal, and thus directly or indirectly to ALGOL 68.

Overview

[edit]

ALGOL 68 features include expression-based syntax, user-declared types and structures/tagged-unions, a reference model of variables and reference parameters, string, array and matrix slicing, and concurrency.

ALGOL 68 was designed by the International Federation for Information Processing (IFIP) IFIP Working Group 2.1 on Algorithmic Languages and Calculi. On 20 December 1968, the language was formally adopted by the group, and then approved for publication by the General Assembly of IFIP.

ALGOL 68 was defined using a formalism, a two-level formal grammar, invented by Adriaan van Wijngaarden. Van Wijngaarden grammars use a context-free grammar to generate an infinite set of productions that will recognize a particular ALGOL 68 program; notably, they are able to express the kind of requirements that in many other programming language technical standards are labelled semantics, and must be expressed in ambiguity-prone natural language prose, and then implemented in compilers as ad hoc code attached to the formal language parser.

ALGOL 68 was the first (and possibly one of the last) major language for which a full formal definition was made before it was implemented.

The main aims and principles of design of ALGOL 68 are:[7]

  1. Completeness and clarity of description
  2. Orthogonality of design
  3. Security
  4. Efficiency:
    • Static mode checking
    • Mode-independent parsing
    • Independent compiling
    • Loop optimizing
    • Representations – in minimal & larger character sets

ALGOL 68 has been criticized, most prominently by some members of its design committee such as C. A. R. Hoare and Edsger Dijkstra, for abandoning the simplicity of ALGOL 60, becoming a vehicle for complex or overly general ideas, and doing little to make the compiler writer's task easier, in contrast to deliberately simple contemporaries (and competitors) such as C, S-algol and Pascal.

In 1970, ALGOL 68-R became the first working compiler for ALGOL 68.

In the 1973 revision, certain features — such as proceduring, gommas[8] and formal bounds — were omitted.[9] Cf. The language of the unrevised report.r0

Though European defence agencies (in Britain Royal Signals and Radar Establishment (RSRE)) promoted the use of ALGOL 68 for its expected security advantages, the American side of the NATO alliance decided to develop a different project, the language Ada, making its use obligatory for US defense contracts.

ALGOL 68 also had a notable influence in the Soviet Union, details of which can be found in Andrey Terekhov's 2014 paper: "ALGOL 68 and Its Impact on the USSR and Russian Programming",[10] and "Алгол 68 и его влияние на программирование в СССР и России".[11]

Steve Bourne, who was on the ALGOL 68 revision committee, took some of its ideas to his Bourne shell (and thereby, to descendant Unix shells such as Bash) and to C (and thereby to descendants such as C++).

The complete history of the project can be found in C. H. Lindsey's "A History of ALGOL 68".[12]

For a full-length treatment of the language, see "Programming ALGOL 68 Made Easy"[13] by Dr. Sian Mountbatten, or "Learning ALGOL 68 Genie"[14] by Marcel van der Veer which includes the Revised Report.

History

[edit]

Origins

[edit]

ALGOL 68, as the name implies, is a follow-on to the ALGOL language that was first formalized in 1960. That same year the International Federation for Information Processing (IFIP) formed and started the Working Group on ALGOL, or WG2.1. This group released an updated ALGOL 60 specification in Rome in April 1962. At a follow-up meeting in March 1964, it was agreed that the group should begin work on two follow-on standards, ALGOL X, which would be a redefinition of the language with some additions, and ALGOL Y, which would have the ability to modify its own programs in the style of the language LISP.[15]

Definition process

[edit]

The first meeting of the ALGOL X group was held in Princeton University in May 1965. A report of the meeting noted two broadly supported themes, the introduction of strong typing and interest in Euler's concepts of 'trees' or 'lists' for handling collections.[16] Although intended as a "short-term solution to existing difficulties",[17] ALGOL X got as far as having a compiler made for it. This compiler was written by Douglas T. Ross of the Massachusetts Institute of Technology (MIT) with the Automated Engineering Design (AED-0) system, also termed ALGOL Extended for Design.[18][19]

At the second meeting in October in France, three formal proposals were presented, Niklaus Wirth's ALGOL W along with comments about record structures by C.A.R. (Tony) Hoare, a similar language by Gerhard Seegmüller, and a paper by Adriaan van Wijngaarden on "Orthogonal design and description of a formal language". The latter, written in almost indecipherable "W-Grammar", proved to be a decisive shift in the evolution of the language. The meeting closed with an agreement that van Wijngaarden would re-write the Wirth/Hoare submission using his W-Grammar.[16]

This seemingly simple task ultimately proved more difficult than expected, and the follow-up meeting had to be delayed six months. When it met in April 1966 in Kootwijk, van Wijngaarden's draft remained incomplete and Wirth and Hoare presented a version using more traditional descriptions. It was generally agreed that their paper was "the right language in the wrong formalism".[20] As these approaches were explored, it became clear there was a difference in the way parameters were described that would have real-world effects, and while Wirth and Hoare protested that further delays might become endless, the committee decided to wait for van Wijngaarden's version. Wirth then implemented their current definition as ALGOL W.[21]

At the next meeting in Warsaw in October 1966,[22] there was an initial report from the I/O Subcommittee who had met at the Oak Ridge National Laboratory and the University of Illinois but had not yet made much progress. The two proposals from the previous meeting were again explored, and this time a new debate emerged about the use of pointers; ALGOL W used them only to refer to records, while van Wijngaarden's version could point to any object. To add confusion, John McCarthy presented a new proposal for operator overloading and the ability to string together and and or constructs, and Klaus Samelson wanted to allow anonymous functions. In the resulting confusion, there was some discussion of abandoning the entire effort.[21] The confusion continued through what was supposed to be the ALGOL Y meeting in Zandvoort in May 1967.[16]

Publication

[edit]

A draft report was finally published in February 1968. This was met by "shock, horror and dissent",[16] mostly due to the hundreds of pages of unreadable grammar and odd terminology. Charles H. Lindsey attempted to figure out what "language was hidden inside of it",[23] a process that took six man-weeks of effort. The resulting paper, "ALGOL 68 with fewer tears",[24] was widely circulated. At a wider information processing meeting in Zürich in May 1968, attendees complained that the language was being forced upon them and that IFIP was "the true villain of this unreasonable situation" as the meetings were mostly closed and there was no formal feedback mechanism. Wirth and Peter Naur formally resigned their authorship positions in WG2.1 at that time.[23]

The next WG2.1 meeting took place in Tirrenia in June 1968. It was supposed to discuss the release of compilers and other issues, but instead devolved into a discussion on the language. van Wijngaarden responded by saying (or threatening) that he would release only one more version of the report. By this point Naur, Hoare, and Wirth had left the effort, and several more were threatening to do so.[25] Several more meetings followed, North Berwick in August 1968, Munich in December which produced the release of the official Report in January 1969 but also resulted in a contentious Minority Report being written. Finally, at Banff, Alberta in September 1969, the project was generally considered complete and the discussion was primarily on errata and a greatly expanded Introduction to the Report.[26]

The effort took five years, burned out many of the greatest names in computer science, and on several occasions became deadlocked over issues both in the definition and the group as a whole. Hoare released a "Critique of ALGOL 68" almost immediately,[27] which has been widely referenced in many works. Wirth went on to further develop the ALGOL W concept and released this as Pascal in 1970.

Implementations

[edit]

ALGOL 68-R

[edit]

The first implementation of the standard, based on the late-1968 draft Report, was introduced by the Royal Radar Establishment in the UK as ALGOL 68-R in July 1970. This was, however, a subset of the full language, and Barry Mailloux, the final editor of the Report, joked that "It is a question of morality. We have a Bible and you are sinning!"[28] This version nevertheless became very popular on the ICL machines, and became a widely used language in military coding, especially in the UK.[29]

Among the changes in 68-R was the requirement for all variables to be declared before their first use. This had a significant advantage that it allowed the compiler to be one-pass, as space for the variables in the activation record was set aside before it was used. However, this change also had the side-effect of demanding the PROCs be declared twice, once as a declaration of the types, and then again as the body of code. Another change was to eliminate the assumed VOID mode, an expression that returns no value (named a statement in other languages) and demanding the word VOID be added where it would have been assumed. Further, 68-R eliminated the explicit parallel processing commands based on PAR.[28]

Others

[edit]

The first full implementation of the language was introduced in 1974 by CDC Netherlands for the Control Data mainframe series. This saw limited use, mostly teaching in Germany and the Netherlands.[29]

A version similar to 68-R was introduced from Carnegie Mellon University in 1976 as 68S, and was again a one-pass compiler based on various simplifications of the original and intended for use on smaller machines like the DEC PDP-11. It too was used mostly for teaching purposes.[29]

A version for IBM mainframes did not become available until 1978, when one was released from Cambridge University. This was "nearly complete". Lindsey released a version for small machines including the IBM PC in 1984.[29]

Three open source Algol 68 implementations are known:[30]

Timeline

[edit]
Year Event Contributor
March 1959 ALGOL Bulletin Issue 1 (First) Peter Naur / ACM
February 1968 Draft Report(DR) Published[33] IFIP Working Group 2.1
March 1968 Algol 68 Final Reportr0 Presented at Munich Meeting IFIP Working Group 2.1
June 1968 Meeting in Tirrenia, Italy IFIP Working Group 2.1
Aug 1968 Meeting in North Berwick, Scotland IFIP Working Group 2.1
December 1968 ALGOL 68 Final Reportr0 Presented at Munich Meeting IFIP Working Group 2.1
April 1970 ALGOL 68-R under GEORGE 3 on an ICL 1907F Royal Signals and Radar Est.
July 1970 ALGOL 68 for the Dartmouth Time-Sharing System[34][35] Sidney Marshall
September 1973 Algol 68 Revised Report[36]r1 Published IFIP Working Group 2.1
1975 ALGOL 68C(C) – transportable compiler (zcode VM) S. Bourne, Andrew Birrell, and Michael Guy
June 1975 G. E. Hedrick and Alan Robertson. The Oklahoma State ALGOL 68 Subset Compiler. 1975 International Conference on ALGOL 68.
June 1977 Strathclyde ALGOL 68 conference, Scotland ACM
May 1978 Proposals for ALGOL H – A Superlanguage of ALGOL 68[37] A. P. Black, V. J. Rayward-Smith
1984 Full ALGOL 68S(S) compiler for Sun, SPARC, and PCs C. H. Lindsey et al, Manchester
August 1988 ALGOL Bulletin Issue 52 (last) Ed. C. H. Lindsey / ACM
May 1997 Algol68 S(S) published on the internet[38] Charles H. Lindsey
November 2001 Algol 68 Genie(G) published on the internet[39] (GNU GPL open source licensing) Marcel van der Veer
January 2025 Algol 68 GCC Front-End published by Jose E. Marchesi under the GPL[32][31] Jose E. Marchesi

The Algorithmic Language ALGOL 68 Reports and Working Group members

[edit]

"Van Wijngaarden once characterized the four authors, somewhat tongue-in-cheek, as: Koster: transputter, Peck: syntaxer, Mailloux: implementer, Van Wijngaarden: party ideologist." – Koster.

Timeline of standardization

[edit]

1968: On 20 December 1968, the "Final Report" (MR 101) was adopted by the Working Group, then subsequently approved by the General Assembly of UNESCO's IFIP for publication. Translations of the standard were made for Russian, German, French and Bulgarian, and then later Japanese and Chinese.[45] The standard was also made available in Braille.

1984: TC 97 considered ALGOL 68 for standardisation as "New Work Item" TC97/N1642 [1][2]. West Germany, Belgium, Netherlands, USSR and Czechoslovakia willing to participate in preparing the standard but the USSR and Czechoslovakia "were not the right kinds of member of the right ISO committees"[3] and Algol 68's ISO standardisation stalled.[4]

1988: Subsequently ALGOL 68 became one of the GOST standards in Russia.

  • GOST 27974-88 Programming language ALGOL 68 — Язык программирования АЛГОЛ 68[46]
  • GOST 27975-88 Programming language ALGOL 68 extended — Язык программирования АЛГОЛ 68 расширенный[47]

Notable language elements

[edit]

Bold symbols and reserved words

[edit]

The standard language contains about sixty reserved words, typically bolded in print, and some with "brief symbol" equivalents:

MODE, OP, PRIO, PROC,
FLEX, HEAP, LOC, LONG, REF, SHORT,
BITS, BOOL, BYTES, CHAR, COMPL, INT, REAL, SEMA, STRING, VOID,
CHANNEL, FILE, FORMAT, STRUCT, UNION,
AT "@", EITHERr0, IS ":=:", ISNT  IS NOTr0 ":/=:" ":≠:", OF "→"r0, TRUE, FALSE, EMPTY, NIL "○", SKIP "~",
CO "¢", COMMENT "¢", PR, PRAGMAT,
CASE ~ IN ~ OUSE ~ IN ~ OUT ~ ESAC "( ~ | ~ |: ~ | ~ | ~ )",
FOR ~ FROM ~ TO ~ BY ~ WHILE ~ DO ~ OD,
IF ~ THEN ~ ELIF ~ THEN ~ ELSE ~ FI "( ~ | ~ |: ~ | ~ | ~ )",
PAR BEGIN ~ END "( ~ )", GO TO, GOTO, EXIT "□"r0.

Units: Expressions

[edit]

The basic language construct is the unit. A unit may be a formula, an enclosed clause, a routine text or one of several technically needed constructs (assignation, jump, skip, nihil). The technical term enclosed clause unifies some of the inherently bracketing constructs known as block, do statement, switch statement in other contemporary languages. When keywords are used, generally the reversed character sequence of the introducing keyword is used for terminating the enclosure, e.g. ( IF ~ THEN ~ ELSE ~ FI, CASE ~ IN ~ OUT ~ ESAC, FOR ~ WHILE ~ DO ~ OD ). This Guarded Command syntax was reused by Stephen Bourne in the common Unix Bourne shell. An expression may also yield a multiple value, which is constructed from other values by a collateral clause. This construct just looks like the parameter pack of a procedure call.

mode: Declarations

[edit]

The basic data types (called modes in Algol 68 parlance) are real, int, compl (complex number), bool, char, bits and bytes. For example:

INT n = 2;
CO n is fixed as a constant of 2. CO
INT m := 3;
CO m is a newly created local variable whose value is initially set to 3. CO
CO    This is short for ref int m = loc int := 3; CO
REAL avogadro = 6.0221415⏨23; CO Avogadro number CO
long long real long long pi = 3.14159 26535 89793 23846 26433 83279 50288 41971 69399 37510;
COMPL square root of minus one = 0 ⊥ 1;

However, the declaration REAL x; is just syntactic sugar for REF REAL x = LOC REAL;. That is, x is really the constant identifier for a reference to a newly generated local REAL variable.

Furthermore, instead of defining both float and double, or int and long and short, etc., ALGOL 68 provides modifiers, so that the presently common double would be written as LONG REAL or LONG LONG REAL instead, for example. The prelude constants max real and min long int are provided to adapt programs to different implementations.

All variables need to be declared, but declaration does not have to precede the first use.

primitive-declarer: INT, REAL, COMPL, COMPLEXG, BOOL, CHAR, STRING, BITS, BYTES, FORMAT, FILE, PIPEG, CHANNEL, SEMA

  • BITS – a "packed vector" of BOOL.
  • BYTES – a "packed vector" of CHAR.
  • STRING – a FLEXible array of CHAR.
  • SEMA – a SEMAphore which can be initialised with the OPerator LEVEL.

Complex types can be created from simpler ones using various type constructors:

  • REF mode – a reference to a value of type mode, similar to & in C/C++ and REF in Pascal
  • STRUCT – used to build structures, like STRUCT in C/C++ and RECORD in Pascal
  • UNION – used to build unions, like in C/C++ and Pascal
  • PROC – used to specify procedures, like functions in C/C++ and procedures/functions in Pascal

Other declaration symbols include: FLEX, HEAP, LOC, REF, LONG, SHORT, EVENTS

  • FLEX – declare the array to be flexible, i.e. it can grow in length on demand.
  • HEAP – allocate variable some free space from the global heap.
  • LOC – allocate variable some free space of the local stack.
  • LONG – declare an INT, REAL or COMPL to be of a LONGer size.
  • SHORT – declare an INT, REAL or COMPL to be of a SHORTer size.

A name for a mode (type) can be declared using a MODE declaration, which is similar to TYPEDEF in C/C++ and TYPE in Pascal:

 INT max=99;
 MODE NEWMODE = [0:9][0:max]STRUCT (
     LONG REAL a, b, c, SHORT INT i, j, k, REF REAL r
 );

This is similar to the following C code:

  const int max=99;
  typedef struct {
      double a, b, c; short i, j, k; float *r;
  } newmode[9+1][max+1];

For ALGOL 68, only the NEWMODE mode-indication appears to the left of the equals symbol, and most notably the construction is made, and can be read, from left to right without regard to priorities. Also, the lower bound of Algol 68 arrays is one by default, but can be any integer from -max int to max int.

Mode declarations allow types to be recursive: defined directly or indirectly in terms of themselves. This is subject to some restrictions – for instance, these declarations are illegal:

 MODE A = REF A
 MODE A = STRUCT (A a, B b)
 MODE A = PROC (A a) A

while these are valid:

 MODE A = STRUCT (REF A a, B b)
 MODE A = PROC (REF A a) REF A

Coercions: casting

[edit]

The coercions produce a coercee from a coercend according to three criteria: the a priori mode of the coercend before the application of any coercion, the a posteriori mode of the coercee required after those coercions, and the syntactic position or "sort" of the coercee. Coercions may be cascaded.

The six possible coercions are termed deproceduring, dereferencing, uniting, widening, rowing, and voiding. Each coercion, except for uniting, prescribes a corresponding dynamic effect on the associated values. Hence, many primitive actions can be programmed implicitly by coercions.

Context strength – allowed coercions:

  • soft – deproceduring
  • weak – dereferencing or deproceduring, yielding a name
  • meek – dereferencing or deproceduring
  • firm – meek, followed by uniting
  • strong – firm, followed by widening, rowing or voiding

Coercion hierarchy with examples

[edit]

ALGOL 68 has a hierarchy of contexts which determine the kind of coercions available at a particular point in the program. These contexts are:

Context
Context location Coercions available Coercion examples in the context
Soft
Weak
Meek
Firm
Strong
Strong
Right hand side of:
  • Identity-declarations, as "~" in: REAL x = ~
  • Initialisations, as "~" in: REAL x := ~

Also:

  • Actual-parameters of calls, as "~" in:PROC: sin(~)
  • Enclosed clauses of casts, as "~" in: REAL(~)
  • Units of routine-texts
  • Statements yielding VOID
  • All parts (but one) of a balanced clause
  • One side of an identity relation, as "~" in: ~ IS ~
deproc​edur​ing
All SOFT then weak derefer​encing (deref​erencing or deproc​eduring, yield​ing a name)
All WEAK then derefer​enc​ing (deref​erenc​ing or deproc​edur​ing)
All MEEK then unit​ing
All FIRM then widen​ing, rowing or voiding

Widening is always applied in the INT to REAL to COMPL direction, provided the modes have the same size. For example: An INT will be coerced to a REAL, but not vice versa. Examples:

  • to REAL from INT
  • to COMPL from REAL
  • to []BOOL from BITS
  • to []CHAR from BYTES

A coercend can also be coerced (rowed) to a multiple of length 1.

For example:

  • to [1]INT from INT
  • to [1]REAL from REAL etc.
Firm
  • Operands of formulas as "~" in:~ OP ~
  • Parameters of transput calls
Example:

UNION(INT,REAL) var := 1

Meek
  • Trimscripts (yielding INT)
  • Enquiries: e.g. as "~" in the following

IF ~ THEN ... FI and FROM ~ BY ~ TO ~ WHILE ~ DO ... OD etc

  • Primaries of calls (e.g. sin in sin(x))
Examples:
  • to BOOL from REF REF BOOL
  • to INT from REF REF REF INT
Weak
  • Primaries of slices, as in "~" in: ~[1:99]
  • Secondaries of selections, as "~" in: value OF ~
Examples:
  • to REF INT from REF REF INT
  • to REF REAL from REF REF REF REAL
  • to REF STRUCT from REF REF REF REF STRUCT
Soft
The LHS of assignments, as "~" in: ~ := ... Example:
  • deproceduring of: PROC REAL random: e.g. random

For more details about Primaries, Secondaries, Tertiary & Quaternaries refer to Operator precedence.

pr & co: Pragmats and Comments

[edit]

Pragmats (from "pragmatic remarks") are directives in the program, typically hints to the compiler; in newer languages these are called "pragmas" (no 't'). e.g.

PRAGMAT heap=32 PRAGMAT
PR heap=32 PR

Comments can be inserted in a variety of ways:

¢ The original way of adding your 2 cents worth to a program ¢
COMMENT "bold" comment COMMENT
CO Style i comment CO
# Style ii comment #
£ This is a hash/pound comment for a UK keyboard £

Normally, comments cannot be nested in ALGOL 68. This restriction can be circumvented by using different comment delimiters (e.g. use hash only for temporary code deletions).

Expressions and compound statements

[edit]

ALGOL 68 being an expression-oriented programming language, the value returned by an assignment statement is a reference to the destination. Thus, the following is valid ALGOL 68 code:

 REAL half pi, one pi; one pi := 2 * ( half pi := 2 * arc tan(1) )

This notion is present in C and Perl, among others. Note that as in earlier languages such as Algol 60 and FORTRAN, spaces are allowed in identifiers, so that half pi is a single identifier (thus avoiding the underscores versus camel case versus all lower-case issues).

As another example, to express the mathematical idea of a sum of f(i) from i=1 to n, the following ALGOL 68 integer expression suffices:

 (INT sum := 0; FOR i TO n DO sum +:= f(i) OD; sum)

Note that, being an integer expression, the former block of code can be used in any context where an integer value can be used. A block of code returns the value of the last expression it evaluated; this idea is present in Lisp, among other languages.

Compound statements are all terminated by distinctive closing brackets:

  • IF choice clauses:
 IF condition THEN statements [ ELSE statements ] FI
 "brief" form:  ( condition | statements | statements )
 IF condition1 THEN statements ELIF condition2 THEN statements [ ELSE statements ] FI
 "brief" form:  ( condition1 | statements |: condition2 | statements | statements )

This scheme not only avoids the dangling else problem but also avoids having to use BEGIN and END in embedded statement sequences.

  • CASE choice clauses:
 CASE switch IN statements, statements,... [ OUT statements ] ESAC
 "brief" form:  ( switch | statements,statements,... | statements )
 CASE switch1 IN statements, statements,... OUSE switch2 IN statements, statements,... [ OUT statements ] ESAC
 "brief" form of CASE statement:  ( switch1 | statements,statements,... |: switch2 | statements,statements,... | statements )

Choice clause example with Brief symbols:

PROC days in month = (INT year, month)INT:
  (month|
    31,
    (year÷×4=0 ∧ year÷×100≠0  ∨  year÷×400=0 | 29 | 28 ),
    31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  );

Choice clause example with Bold symbols:

PROC days in month = (INT year, month)INT:
  CASE month IN
    31,
    IF year MOD 4 EQ 0 AND year MOD 100 NE 0  OR  year MOD 400 EQ 0 THEN 29 ELSE 28 FI,
    31, 30, 31, 30, 31, 31, 30, 31, 30, 31
  ESAC;

Choice clause example mixing Bold and Brief symbols:

PROC days in month = (INT year, month)INT:
  CASE month IN
¢Jan¢ 31,
¢Feb¢ ( year MOD 4 = 0 AND year MOD 100 ≠ 0  OR  year MOD 400 = 0 | 29 | 28 ),
¢Mar¢ 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ¢ to Dec. ¢
  ESAC;

Algol68 allowed the switch to be of either type INT or (uniquely) UNION. The latter allows the enforcing strong typing onto UNION variables. cf. union below for example.

  • do loop clause:
 [ FOR index ] [ FROM first ] [ BY increment ] [ TO last ] [ WHILE condition ] DO statements OD
 The minimum form of a "loop clause" is thus: DO statements OD

This was considered the "universal" loop, the full syntax is:

FOR i FROM 1 BY -22 TO -333 WHILE i×i≠4444 DO ~ OD

The construct have several unusual aspects:

  • only the DO ~ OD portion was compulsory, in which case the loop will iterate indefinitely.
  • thus the clause TO 100 DO ~ OD, will iterate only 100 times.
  • the WHILE "syntactic element" allowed a programmer to break from a FOR loop early. e.g.
INT sum sq:=0;
FOR i
WHILE
  print(("So far:",i,newline));
  sum sq≠70↑2
DO
  sum sq+:=i↑2
OD

Subsequent "extensions" to the standard Algol68 allowed the TO syntactic element to be replaced with UPTO and DOWNTO to achieve a small optimisation. The same compilers also incorporated:

  • UNTIL(C) – for late loop termination.
  • FOREACH(S) – for working on arrays in parallel.

Further examples can be found in the code examples below.

struct, union & [:]: Structures, unions and arrays

[edit]

ALGOL 68 supports arrays with any number of dimensions, and it allows for the slicing of whole or partial rows or columns.

 MODE VECTOR = [1:3]    REAL;   # vector MODE declaration (typedef)  #
 MODE MATRIX = [1:3,1:3]REAL;   # matrix MODE declaration (typedef)  #
 VECTOR v1  := (1,2,3);         # array variable initially (1,2,3)   #
 []REAL v2   = (4,5,6);         # constant array, type equivalent to VECTOR, bounds are implied  #
 OP + = (VECTOR a,b) VECTOR:    # binary OPerator definition         #
   (VECTOR out; FOR i FROM ⌊a TO ⌈a DO out[i] := a[i]+b[i] OD; out);
 MATRIX m := (v1, v2, v1+v2);
 print ((m[,2:]));              # a slice of the 2nd and 3rd columns #

Matrices can be sliced either way, e.g.:

 REF VECTOR row = m[2,];  # define a REF (pointer) to the 2nd row #
 REF VECTOR col = m[,2];  # define a REF (pointer) to the 2nd column #

ALGOL 68 supports multiple field structures (STRUCT) and united modes. Reference variables may point to any MODE including array slices and structure fields.

For an example of all this, here is the traditional linked list declaration:

 MODE NODE = UNION (VOID, REAL, INT, COMPL, STRING);
 MODE LIST = STRUCT (NODE val, REF LIST next);

Usage example for UNION CASE of NODE:

Algol68r0 as in the 1968 Final Report Algol68r1 as in the 1973 Revised Report
 NODE n := "1234";
 REAL r; INT i; COMPL c; STRING s
 CASE r,i,c,s::=n IN
   print(("real:", r)),
   print(("int:", i)),
   print(("compl:", c)),
   print(("string:", s))
   OUT print(("?:", n))
 ESAC
 NODE n := "1234";
 # or n := EMPTY; #
  CASE n IN
   (VOID):     print(("void:", "EMPTY")),
   (REAL r):   print(("real:", r)),
   (INT i):    print(("int:", i)),
   (COMPL c):  print(("compl:", c)),
   (STRING s): print(("string:", s))
   OUT         print(("?:", n))
 ESAC

proc: Procedures

[edit]

Procedure (PROC) declarations require type specifications for both the parameters and the result (VOID if none):

 PROC max of real = (REAL a, b) REAL:
    IF a > b THEN a ELSE b FI;

or, using the "brief" form of the conditional statement:

 PROC max of real = (REAL a, b) REAL: (a>b | a | b);

The return value of a proc is the value of the last expression evaluated in the procedure. References to procedures (ref proc) are also permitted. Call-by-reference parameters are provided by specifying references (such as ref real) in the formal argument list. The following example defines a procedure that applies a function (specified as a parameter) to each element of an array:

 PROC apply = (REF [] REAL a, PROC (REAL) REAL f):
  
    FOR i FROM LWB a TO UPB a DO a[i] := f(a[i]) OD

This simplicity of code was unachievable in ALGOL 68's predecessor ALGOL 60.

op: Operators

[edit]

The programmer may define new operators and both those and the pre-defined ones may be overloaded and their priorities may be changed by the coder. The following example defines operator MAX with both dyadic and monadic versions (scanning across the elements of an array).

 PRIO MAX = 9;
  
 OP MAX = (INT a,b) INT: ( a>b | a | b );
 OP MAX = (REAL a,b) REAL: ( a>b | a | b );
 OP MAX = (COMPL a,b) COMPL: ( ABS a > ABS b | a | b );
  
 OP MAX = ([]REAL a) REAL:
    (REAL out := a[LWB a];
     FOR i FROM LWB a + 1 TO UPB a DO ( a[i]>out | out:=a[i] ) OD;
     out)

Array, Procedure, Dereference and coercion operations

[edit]
PRIOrity Operation r0&r1 +Algol68r0 +Algol68G
Effectively 12
(Primary)
dereferencing, deproceduring(~,~), subscripting[~], rowing[~,], slicing[~:~], size denotations LONG & SHORT proceduring currying(~,,,), DIAG, TRNSP, ROW, COL
Effectively 11
(Secondary)
OF (selection), LOC & HEAP (generators) → (selection) NEW (generators)

These are technically not operators, rather they are considered "units associated with names"

Monadic operators

[edit]
PRIOrity
(Tertiary)
Algol68 "Worthy characters[5]"r0&r1 +Algol68r0&r1 +Algol68C,G +Algol68r0
10 NOT ~, UP, DOWN, LWB, UPB,

-, ABS, ARG, BIN, ENTIER, LENG, LEVEL, ODD, REPR, ROUND, SHORTEN

¬, ↑, ↓, ⌊, ⌈ NORM, TRACE, T, DET, INV LWS, UPS, ⎩, ⎧, BTB, CTB

Dyadic operators with associated priorities

[edit]
PRIOrity
(Tertiary)
Algol68 "Worthy characters"r0&r1 +Algol68r0&r1 +Algol68C,G +Algol68r0
9 +*, I +×, ⊥ !
8 SHL, SHR, **, UP, DOWN, LWB, UPB ↑, ↓, ⌊, ⌈ ××, ^, LWS, UPS, ⎩, ⎧
7 *, /,  %, OVER,  %*, MOD, ELEM ×, ÷, ÷×, ÷*, %×, □ ÷:
6 -, +
5 <, LT, <=, LE, >=, GE, >, GT ≤, ≥
4 EQ =, NE ~= /= ≠, ¬=
3 &, AND /\
2 OR \/
1 MINUSAB, PLUSAB, TIMESAB, DIVAB, OVERAB, MODAB, PLUSTO,

-:=, +:=, *:=, /:=, %:=, %*:=, +=:

×:=, ÷:=, ÷×:=, ÷*:=,  %×:= MINUS, PLUS, DIV, OVERB, MODB, ÷::=, PRUS

Specific details:

  • Tertiaries include names NIL and ○.
  • LWS: In Algol68r0 the operators LWS and ⎩ ... both return TRUE if the lower state of the dimension of an array is fixed.
  • The UPS and ⎧ operators are similar on the upper state.
  • The LWB and UPB operators are automatically available on UNIONs of different orders (and MODEs) of arrays. eg. UPB of union([]int, [,]real, flex[,,,]char)

Assignation and identity relations, etc.

[edit]

These are technically not operators, rather they are considered "units associated with names"

PRIOrity
(Quaternaries)
Algol68 "Worthy characters"r0&r1 +Algol68r0&r1 +Algol68C,G,R +Algol68r0
Effectively 0 :=, IS :=:, ISNT :/=: :~=:, AT @, ":", ";" :≠: :¬=: :=:=C, =:=R ..=, .=, CT, ::, CTAB, ::=, .., is not, "..", ".,"

Note: Quaternaries include names SKIP and ~.

:=: (alternatively IS) tests if two pointers are equal; :/=: (alternatively ISNT) tests if they are unequal.

Why :=: and :/=: are needed
[edit]

Consider trying to compare two pointer values, such as the following variables, declared as pointers-to-integer:

REF INT ip, jp

Now consider how to decide whether these two are pointing to the same location, or whether one of them is pointing to NIL. The following expression

ip = jp

will dereference both pointers down to values of type INT, and compare those, since the = operator is defined for INT, but not REF INT. It is not legal to define = for operands of type REF INT and INT at the same time, because then calls become ambiguous, due to the implicit coercions that can be applied: should the operands be left as REF INT and that version of the operator called? Or should they be dereferenced further to INT and that version used instead? Therefore the following expression can never be made legal:

ip = NIL

Hence the need for separate constructs not subject to the normal coercion rules for operands to operators. But there is a gotcha. The following expressions:

ip :=: jp
ip :=: NIL

while legal, will probably not do what might be expected. They will always return FALSE, because they are comparing the actual addresses of the variables ip and jp, rather than what they point to. To achieve the right effect, one would have to write

ip :=: REF INT(jp)
ip :=: REF INT(NIL)

Special characters

[edit]
IBM 2741 keyboard with APL symbols

Most of Algol's "special" characters (⊂, ≡, ␣, ×, ÷, ≤, ≥, ≠, ¬, ⊃, ≡, ∨, ∧, →, ↓, ↑, ⌊, ⌈, ⎩, ⎧, ⊥, ⏨, ¢, ○ and □) can be found on the IBM 2741 keyboard with the APL "golf-ball" print head inserted; these became available in the mid-1960s while ALGOL 68 was being drafted. These characters are also part of the Unicode standard and most of them are available in several popular fonts.

transput: Input and output

[edit]

Transput is the term used to refer to ALGOL 68's input and output facilities. It includes pre-defined procedures for unformatted, formatted and binary transput. Files and other transput devices are handled in a consistent and machine-independent manner. The following example prints out some unformatted output to the standard output device:

  print ((newpage, "Title", newline, "Value of i is ",
    i, "and x[i] is ", x[i], newline))

Note the predefined procedures newpage and newline passed as arguments.

Books, channels and files

[edit]

The TRANSPUT is considered to be of BOOKS, CHANNELS and FILES:

  • Books are made up of pages, lines and characters, and may be backed up by files.
    • A specific book can be located by name with a call to match.
  • CHANNELs correspond to physical devices. e.g. card punches and printers.
    • Three standard channels are distinguished: stand in channel, stand out channel, stand back channel.
  • A FILE is a means of communicating between a program and a book that has been opened via some channel.
    • The MOOD of a file may be read, write, char, bin, and opened.
    • transput procedures include: establish, create, open, associate, lock, close, scratch.
    • position enquires: char number, line number, page number.
    • layout routines include:
      • space, backspace, newline, newpage.
      • get good line, get good page, get good book, and PROC set=(REF FILE f, INT page,line,char)VOID:
    • A file has event routines. e.g. on logical file end, on physical file end, on page end, on line end, on format end, on value error, on char error.

formatted transput

[edit]

"Formatted transput" in ALGOL 68's transput has its own syntax and patterns (functions), with FORMATs embedded between two $ characters.[48]

Examples:

 printf (($2l"The sum is:"x, g(0)$, m + n)); ¢ prints the same as: ¢
 print ((new line, new line, "The sum is:", space, whole (m + n, 0))

par: Parallel processing

[edit]

ALGOL 68 supports programming of parallel processing. Using the keyword PAR, a collateral clause is converted to a parallel clause, where the synchronisation of actions is controlled using semaphores. In A68G the parallel actions are mapped to threads when available on the hosting operating system. In A68S a different paradigm of parallel processing was implemented (see below).

PROC
    eat = VOID: ( muffins-:=1; print(("Yum!",new line))),
    speak = VOID: ( words-:=1; print(("Yak...",new line)));
 
INT muffins := 4, words := 8;
SEMA mouth = LEVEL 1;
 
PAR BEGIN
    WHILE muffins > 0 DO
        DOWN mouth;
        eat;
        UP mouth
    OD,
    WHILE words > 0 DO
        DOWN mouth;
        speak;
        UP mouth
    OD
END

Miscellaneous

[edit]

For its technical intricacies, ALGOL 68 needs a cornucopia of methods to deny the existence of something:

SKIP, "~" or "?"C – an undefined value always syntactically valid,
EMPTY – the only value admissible to VOID, needed for selecting VOID in a UNION,
VOID – syntactically like a MODE, but not one,
NIL or "○" – a name not denoting anything, of an unspecified reference mode,
() or specifically [1:0]INT – a vacuum is an empty array (here specifically of MODE []INT).
undefined – a standards reports procedure raising an exception in the runtime system.
ℵ – Used in the standards report to inhibit introspection of certain types. e.g. SEMA

The term NIL IS var always evaluates to TRUE for any variable (but see above for correct use of IS :/=:), whereas it is not known to which value a comparison x < SKIP evaluates for any integer x.

ALGOL 68 leaves intentionally undefined what happens in case of integer overflow, the integer bit representation, and the degree of numerical accuracy for floating point.

Both official reports included some advanced features that were not part of the standard language. These were indicated with an ℵ and considered effectively private. Examples include "≮" and "≯" for templates, the OUTTYPE/INTYPE for crude duck typing, and the STRAIGHTOUT and STRAIGHTIN operators for "straightening" nested arrays and structures

Examples of use

[edit]

Code sample

[edit]

This sample program implements the Sieve of Eratosthenes to find all the prime numbers that are less than 100. NIL is the ALGOL 68 analogue of the null pointer in other languages. The notation x OF y accesses a member x of a STRUCT y.

BEGIN # Algol-68 prime number sieve, functional style #
  
  PROC error = (STRING s) VOID:
     (print(( newline, " error: ", s, newline)); GOTO stop);
  PROC one to = (INT n) LIST:
     (PROC f = (INT m,n) LIST: (m>n | NIL | cons(m, f(m+1,n))); f(1,n));
  
  MODE LIST = REF NODE;
  MODE NODE = STRUCT (INT h, LIST t);
  PROC cons = (INT n, LIST l) LIST: HEAP NODE := (n,l);
  PROC hd   = (LIST l) INT: ( l IS NIL | error("hd NIL"); SKIP | h OF l );
  PROC tl   = (LIST l) LIST: ( l IS NIL | error("tl NIL"); SKIP | t OF l );
  PROC show = (LIST l) VOID: ( l ISNT NIL | print((" ",whole(hd(l),0))); show(tl(l)));
  
  PROC filter = (PROC (INT) BOOL p, LIST l) LIST:
     IF l IS NIL THEN NIL
     ELIF p(hd(l)) THEN cons(hd(l), filter(p,tl(l)))
     ELSE filter(p, tl(l))
     FI;
  
  PROC sieve = (LIST l) LIST:
     IF l IS NIL THEN NIL
     ELSE
        PROC not multiple = (INT n) BOOL: n MOD hd(l) ~= 0;
        cons(hd(l), sieve( filter( not multiple, tl(l) )))
     FI;
  
  PROC primes = (INT n) LIST: sieve( tl( one to(n) ));
  
  show( primes(100) )
END

Operating systems written in ALGOL 68

[edit]
  • Cambridge CAP computer – All procedures constituting the operating system were written in ALGOL 68C, although several other closely associated protected procedures, such as a paginator, are written in BCPL.[49]
  • Eldon 3 – Developed at Leeds University for the ICL 1900 was written in ALGOL 68-R.[50]
  • Flex machine – The hardware was custom and microprogrammable, with an operating system, (modular) compiler, editor, garbage collector and filing system all written in ALGOL 68RS. The command shell Curt[51] was designed to access typed data similar to Algol-68 modes.
  • VMES3 was the implementation language of the operating system VME. S3 was based on ALGOL 68 but with data types and operators aligned to those offered by the ICL 2900 Series.

Note: The Soviet Era computers Эльбрус-1 (Elbrus-1) and Эльбрус-2 were created using high-level language Эль-76 (AL-76), rather than the traditional assembly. Эль-76 resembles Algol-68, The main difference is the dynamic binding types in Эль-76 supported at the hardware level. Эль-76 is used for application, job control, system programming.[52]

Applications

[edit]

Both ALGOL 68C and ALGOL 68-R are written in ALGOL 68, effectively making ALGOL 68 an application of itself. Other applications include:

Libraries and APIs

[edit]

Program representation

[edit]

A feature of ALGOL 68, inherited from the ALGOL tradition, is its different representations. Programs in the strict language (which is rigorously defined in the Report) denote production trees in the form of a sequence of grammar symbols, and should be represented using some representation language, of which there are many and tailored to different purposes.

  • Representation languages that are intended to describe algorithms in printed works are known as publication languages and typically make use of rich typography to denote bold words and operator indications.
  • Representation languages that are intended to be used in compiler input, what we would call programming languages, are limited by the restrictions imposed by input methods and character sets and have to resort to stropping regimes to distinguish between bold and non bold letters and digits.
  • Representation languages that are intended to be both produced and consumed by computers, known as hardware languages, would typically use a binary compact representation.

The Revised Report defines a reference language and it is recommended for representation languages that are intended to be read by humans to be close enough to the reference language so symbols can be distinguished "without further elucidation". These representation languages are called implementations of the reference language.

For example, the construct in the strict language bold-begin-symbol could be represented as begin in a publication language, as BEGIN in a programming language or as the bytes 0xC000 in some hardware language. Similarly, the strict language differs from symbol could be represented as ≠ or as /=.

ALGOL 68's reserved words are effectively in a different namespace from identifiers, and spaces are allowed in identifiers in most stropping regimes, so this next fragment is legal:

 INT a real int = 3 ;

The programmer who writes executable code does not always have an option of BOLD typeface or underlining in the code as this may depend on hardware and cultural issues. Different methods to denote these identifiers have been devised. This is called a stropping regime. For example, all or some of the following may be available programming representations:

'INT'A REAL INT = 3; # QUOTE stropping style #
.INT A REAL INT = 3; # POINT stropping style #
 INT a real int = 3; # UPPER stropping style #
 int a_real_int = 3; # RES stropping style, there are 61 accepted reserved words #

All implementations must recognize at least POINT, UPPER and RES inside PRAGMAT sections. Of these, POINT and UPPER stropping are quite common. QUOTE (single apostrophe quoting) was the original recommendation[citation needed].

It may seem that RES stropping is a contradiction to the specification, as there are no reserved words in Algol 68. This is not so. In RES stropping the representation of the bold word (or keyword) begin is begin, and the representation of the identifier begin is begin_. Note that the underscore character is just a representation artifact and not part of the represented identifier. In contrast, in non-stropped languages with reserved words, like for example C, it is not possible to represent an identifier if, since the representation if_ represents the identifier if_, not if.

The following characters were recommended for portability, and termed "worthy characters" in the Report on the Standard Hardware Representation of Algol 68 :

  • ^ Worthy Characters: ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 "#$%'()*+,-./:;<=>@[ ]_|

This reflected a problem in the 1960s where some hardware didn't support lower-case, nor some other non-ASCII characters, indeed in the 1973 report it was written: "Four worthy characters — "|", "_", "[", and "]" — are often coded differently, even at installations which nominally use the same character set."

  • Base characters: "Worthy characters" are a subset of "base characters".

Example of different program representations

[edit]
Representation Code
Algol68 as typically published
¢ underline or 
   bold typeface ¢
 mode xint = int;
 xint sum sq:=0;
 for i while
   sum sq≠70×70
 do
   sum sq+:=i↑2
 od
Quote stropping
(like wikitext)
'pr' quote 'pr'
'mode' 'xint' = 'int';
'xint' sum sq:=0;
'for' i 'while'
  sum sq≠70×70
'do'
  sum sq+:=i↑2
'od'
For a 7-bit character code compiler
PR UPPER PR
MODE XINT = INT;
XINT sum sq:=0;
FOR i WHILE
  sum sq/=70*70
DO
  sum sq+:=i**2
OD
For a 6-bit character code compiler
.PR POINT .PR
.MODE .XINT = .INT;
.XINT SUM SQ:=0;
.FOR I .WHILE
  SUM SQ .NE 70*70
.DO
  SUM SQ .PLUSAB I .UP 2
.OD
Algol68 using RES stropping
(reserved word)
.PR RES .PR
mode .xint = int;
.xint sum sq:=0;
for i while
  sum sq≠70×70
do
  sum sq+:=i↑2
od

ALGOL 68 allows for every natural language to define its own set of keywords Algol-68. As a result, programmers are able to write programs using keywords from their native language. Below is an example of a simple procedure that calculates "the day following", the code is in two languages: English and German.[citation needed]

 # Next day date - English variant #
 MODE DATE = STRUCT(INT day, STRING month, INT year);
 PROC the day following = (DATE x) DATE:
      IF day OF  x < length of month (month OF x, year OF x)
      THEN (day OF x + 1, month OF x, year OF x)
      ELIF month OF x = "December"
      THEN (1, "January", year OF x + 1)
      ELSE (1, successor of month (month OF x), year OF x)
      FI;
 # Nachfolgetag - Deutsche Variante #
 MENGE DATUM = TUPEL(GANZ tag, WORT monat, GANZ jahr);
 FUNKTION naechster tag nach = (DATUM x) DATUM:
          WENN tag VON x < monatslaenge(monat VON x, jahr VON x)
          DANN (tag VON x + 1, monat VON x, jahr VON x)
          WENNABER monat VON x = "Dezember"
          DANN (1, "Januar", jahr VON x + 1)
          ANSONSTEN (1, nachfolgemonat(monat VON x), jahr VON x)
          ENDEWENN;

Russian/Soviet example: In English Algol68's case statement reads CASE ~ IN ~ OUT ~ ESAC, in Cyrillic this reads выб ~ в ~ либо ~ быв.

Revisions

[edit]

Except where noted (with a superscript), the language described above is that of the "Revised Report(r1)".

The language of the unrevised report

[edit]

The original language (As per the "Final Report"r0) differs in syntax of the mode cast, and it had the feature of proceduring, i.e. coercing the value of a term into a procedure which evaluates the term. Proceduring would be intended to make evaluations lazy. The most useful application could have been the short-circuited evaluation of Boolean operators. In:

OP ANDF = (BOOL a,PROC BOOL b)BOOL:(a | b | FALSE);
OP ORF = (BOOL a,PROC BOOL b)BOOL:(a | TRUE | b);

b is only evaluated if a is true.

As defined in ALGOL 68, it did not work as expected, for example in the code:

IF FALSE ANDF CO proc bool: CO ( print ("Should not be executed"); TRUE)
THEN ...

against the programmers naïve expectations the print would be executed as it is only the value of the elaborated enclosed-clause after ANDF that was procedured. Textual insertion of the commented-out PROC BOOL: makes it work.

Some implementations emulate the expected behaviour for this special case by extension of the language.

Before revision, the programmer could decide to have the arguments of a procedure evaluated serially instead of collaterally by using semicolons instead of commas (gommas).

For example in:

PROC test = (REAL a; REAL b) :...
...
test (x PLUS 1, x);

The first argument to test is guaranteed to be evaluated before the second, but in the usual:

PROC test = (REAL a, b) :...
...
test (x PLUS 1, x);

then the compiler could evaluate the arguments in whatever order it felt like.

Extension proposals from IFIP WG 2.1

[edit]

After the revision of the report, some extensions to the language have been proposed to widen the applicability:

  • partial parametrisation (aka Currying): creation of functions (with fewer parameters) by specification of some, but not all parameters for a call, e.g. a function logarithm of two parameters, base and argument, could be specialised to natural, binary or decadic log,[55]
  • module extension: for support of external linkage, two mechanisms were proposed, bottom-up definition modules, a more powerful version of the facilities from ALGOL 68-R and top-down holes, similar to the ENVIRON and USING clauses from ALGOL 68C[56]
  • mode parameters: for implementation of limited parametrical polymorphism (most operations on data structures like lists, trees or other data containers can be specified without touching the pay load).[57]

So far, only partial parametrisation has been implemented, in Algol 68 Genie.

True ALGOL 68s specification and implementation timeline

[edit]
Name Year Purpose State Description Target CPU Licensing Implementation language
Generalized ALGOL 1962 Scientific NLD ALGOL for generalised grammars
ALGOL YY 1966 Draft proposal Intl First version of Algol 68 Specification ACM
ALGOL 68DR 1968 Draft proposal Intl IFIP WG 2.1 Draft Report Specification – March ACM
ALGOL 68r0 1968 Standard Intl IFIP WG 2.1 Final Report Specification – August ACM
ALGOL 68-RR 1970 Military UK ICL 1900 ALGOL 60
EPOS ALGOLE 1971 Scientific
ALGOL 68RSRS 1972 Multi-purpose UK Portable compiler system ICL 2900/Series 39, Multics, VMS & C generator (1993) Crown Copyright ALGOL 68RS
Algol 68 with areas 1972 Experimental & other UK Addition of areas to Algol 68
Mini ALGOL 68 1973 Research NLD Interpreter for ALGOL 68 subset[58] Portable interpreter Mathematisch Centrum ALGOL 60
OREGANO 1973 Research US "The importance of implementation models." UCLA
ALGOL 68CC 1975 Scientific UK Cambridge Algol 68 ICL, IBM 360, PDP-10 & Unix, Telefunken, TESLA 200,[59] Z80 (1980)[60] Cambridge ALGOL 68C
ALGOL 68 Revised Reportr1 1975 Standard Intl IFIP WG 2.1 Revised Report Specification ACM
Algol HH 1975 Experimental & other UK Proposed extensions to the mode system of Algol 68 Specification ALGOL W
Odra Algol 68 1976 practical uses Soviet Union/ Poland Odra 1204/IL Soviet ALGOL 60
Oklahoma ALGOL 68 1976 programming instruction USA Oklahoma State University implementation[61][62] IBM 1130 and System/370/158 Unknown ANSI Fortran 66.
Berlin ALGOL 68 1977 Research DE Portable compiler for System/370, Siemens S4004, and PDP-11[63][64] Machine-independent compiler Technische Universität Berlin CDL 2
FLACCF 1977 Multi-purpose CAN Revised Report complete implementation with debug features System/370 lease, Chion Corporation Assembler
ALGOL 68-RTRT 1979 Scientific UK Parallel ALGOL 68-R
RS Algolrs 1979 Scientific UK
ALGOL 68+ 1980 Scientific NLD Proposed superlanguage of ALGOL 68[65]
M-220 ALGOL 68 Soviet Union M-220 Soviet EPSILON
Leningrad ALGOL 68L 1980 Telecommunications Soviet Union Full language + modules IBM, DEC, CAMCOH, PS 1001 & PC Soviet
Interactive ALGOL 68I 1983 UK Incremental compilation PC Noncommercial shareware
ALGOL 68SS 1985 Scientific Intl Sun version of ALGOL 68 Sun-3, Sun SPARC (under SunOS 4.1 & Solaris 2), Atari ST (under GEMDOS), Acorn Archimedes (under RISC OS), VAX-11 under Ultrix-32
Algol68toC[66] (ctrans) 1985 Electronics UK ctrans from ELLA ALGOL 68RS Portable C generator  Open-source software (1995) ALGOL 68RS
MK2 Interactive ALGOL 68 1992 UK Incremental compilation PC Noncommercial shareware[67]
Algol 68 GenieG 2001 Full language NLD Includes standard collateral clause Portable interpreter GPL C
Algol 68 Genie version 2.0.0 2010 Full language NLD Portable interpreter; optional compilation of selected units GPL C
GCC (ga68) 2025 Full language ESP GCC Front-End Portable compiler GPL C++

The S3 language that was used to write the ICL VME operating system and much other system software on the ICL 2900 Series was a direct derivative of Algol 68. However, it omitted many of the more complex features, and replaced the basic modes with a set of data types that mapped directly to the 2900 Series hardware architecture.

Implementation specific extensions

[edit]

ALGOL 68R from RRE was the first ALGOL 68 subset implementation, running on the ICL 1900. Based on the original language, the main subset restrictions were definition before use and no parallel processing. This compiler was popular in UK universities in the 1970s, where many computer science students learnt ALGOL 68 as their first programming language; the compiler was renowned for good error messages.

ALGOL 68RS(RS) from RSRE was a portable compiler system written in ALGOL 68RS (bootstrapped from ALGOL 68R), and implemented on a variety of systems including the ICL 2900/Series 39, Multics and DEC VAX/VMS. The language was based on the Revised Report, but with similar subset restrictions to ALGOL 68R. This compiler survives in the form of an Algol68-to-C compiler.

In ALGOL 68S(S) from Carnegie Mellon University the power of parallel processing was improved by adding an orthogonal extension, eventing. Any variable declaration containing keyword EVENT made assignments to this variable eligible for parallel evaluation, i.e. the right hand side was made into a procedure which was moved to one of the processors of the C.mmp multiprocessor system. Accesses to such variables were delayed after termination of the assignment.

Cambridge ALGOL 68C(C) was a portable compiler that implemented a subset of ALGOL 68, restricting operator definitions and omitting garbage collection, flexible rows and formatted transput.

Algol 68 Genie(G) by M. van der Veer is an ALGOL 68 implementation for today's computers and operating systems.

"Despite good intentions, a programmer may violate portability by inadvertently employing a local extension. To guard against this, each implementation should provide a PORTCHECK pragmat option. While this option is in force, the compiler prints a message for each construct that it recognizes as violating some portability constraint."[68]

Quotes

[edit]
  • ... The scheme of type composition adopted by C owes considerable debt to Algol 68, although it did not, perhaps, emerge in a form that Algol's adherents would approve of. The central notion I captured from Algol was a type structure based on atomic types (including structures), composed into arrays, pointers (references), and functions (procedures). Algol 68's concept of unions and casts also had an influence that appeared later. Dennis Ritchie Apr 1993.[2]
  • ... C does not descend from Algol 68 is true, yet there was influence, much of it so subtle that it is hard to recover even when I think hard. In particular, the union type (a late addition to C) does owe to A68, not in any details, but in the idea of having such a type at all. More deeply, the type structure in general and even, in some strange way, the declaration syntax (the type-constructor part) was inspired by A68. And yes, of course, "long". Dennis Ritchie, 18 June 1988[3]
  • "Congratulations, your Master has done it" – Niklaus Wirth[69]
  • The more I see of it, the more unhappy I become – E. W. Dijkstra, 1968[70]
  • [...] it was said that A68's popularity was inversely proportional to [...] the distance from AmsterdamGuido van Rossum[71]
  • [...] The best we could do was to send with it a minority report, stating our considered view that, "... as a tool for the reliable creation of sophisticated programs, the language was a failure." [...] C. A. R. Hoare in his Oct 1980 Turing Award Lecture[72]
  • "[...] More than ever it will be required from an adequate programming tool that it assists, by structure, the programmer in the most difficult aspects of his job, viz. in the reliable creation of sophisticated programs. In this respect we fail to see how the language proposed here is a significant step forward: on the contrary, we feel that its implicit view of the programmer's task is very much the same as, say, ten years ago. This forces upon us the conclusion that, regarded as a programming tool, the language must be regarded as obsolete. [...]" 1968 Working Group minority report on 23 December 1968.[73]

See also

[edit]

References

[edit]
[edit]
Revisions and contributorsEdit on WikipediaRead on Wikipedia
from Grokipedia
ALGOL 68 is a general-purpose, procedural programming language intended for formulating algorithms executable by computers or interpretable by humans, emphasizing mathematical precision and generality in expression. It features a strongly typed, orthogonal system of "modes" that generalizes data types to permit an infinite variety, including dynamic arrays, unions, and procedures as first-class values. Developed by the International Federation for Information Processing (IFIP) Working Group 2.1 during the late 1960s, the language's definitive specification appeared in the Revised Report on the Algorithmic Language ALGOL 68 in 1973, following contentious debates within the committee that included resignations and a dissenting minority report decrying its complexity. Key innovations encompassed user-definable operators, parallel clause execution for concurrency hints, and a syntax blending orthogonality with metalinguistic annotations via "metanotionals" for rigorous yet flexible definition, aiming to resolve limitations in ALGOL 60 such as rigid typing and scope rules. Although praised for advancing concepts like strong typing and modularity that permeated later languages, ALGOL 68's elaborate syntax and steep implementation demands restricted its practical uptake, with adoption largely confined to academic and specialized environments rather than broad commercial success.

Introduction

Design Goals and Principles

The design of ALGOL 68, developed by Working Group 2.1 on ALGOL of the International Federation for Information Processing (IFIP), prioritized creating a general-purpose algorithmic language suitable for diverse applications, efficient execution on varied computers, and effective communication of algorithms across international boundaries. This effort built on experience with ALGOL 60 while addressing its limitations through a revised specification that balanced expressive power with implementability, as directed by IFIP Technical Committee 2. The core principles, articulated in the Revised Report published in 1973, emphasized completeness, orthogonality, security, and efficiency to ensure the language's theoretical soundness and practical utility. Completeness required that all syntactically valid programs possess a precisely defined semantics, eschewing ad hoc exclusions to enable the full expression of mathematically definable algorithms without ambiguity. Orthogonality mandated independent, freely combinable features to minimize redundant primitives, fostering consistency, ease of learning, and maximal flexibility in program construction while avoiding interactions that could compromise predictability. Security incorporated compile-time and runtime checks, such as static mode checking, to preclude common errors like type mismatches, thereby enhancing reliability without overly constraining programmers. Efficiency targeted resource-effective implementations via mode-independent compilation, loop optimizations, and a minimal character set, allowing portable code execution across hardware without demanding intricate optimizations. Generality extended the 's scope to encompass both high-level abstractions and low-level control, supporting scientific computation, , and education, while clarity in formal description—achieved through the two-level Van Wijngaarden grammar—facilitated unambiguous specification and implementation fidelity. These principles collectively aimed to produce a that was powerful yet simple, readable, and maintainable, serving as both a practical tool and a basis for algorithmic study.

Key Characteristics and Innovations

ALGOL 68 introduced a highly orthogonal , minimizing the number of primitive concepts while ensuring their consistent application across constructs to maximize expressive power and ease of use. This , combined with syntactic flexibility, allowed features like modes and operators to combine independently without ad hoc restrictions, differing from the more rigid structures in predecessors like ALGOL 60. The 's syntax was formally defined using a two-level Van Wijngaarden grammar, comprising hyper-rules and metaproductions, which enabled precise, context-dependent specification and handled and through elaboration rules, marking a significant advance in rigorous definition. Central to ALGOL 68's were modes, an extensible framework supporting infinite types including plain (e.g., , real), structured, , procedure, and united modes, with declarations allowing recursive and higher-order types. Coercions provided principled implicit conversions—such as widening (integer to real), dereferencing, and uniting—cascadable in chains, enhancing while reducing verbosity, though requiring static checks for security. Most errors, including type mismatches, were detectable at due to strong static typing, except for runtime checks on united types. The language emphasized expression-oriented semantics, where nearly all statements (units) yielded values, enabling composable constructs like value-returning assignments and conditionals (e.g., av := IF iv < 0 THEN -iv ELSE iv FI). Innovations included user-defined operators with customizable priorities and associativity, nested procedures as full closures, and support for parallel elaboration via collateral and parallel clauses for concurrent execution hints. Flexible declarations permitted mode and variable definitions anywhere within scopes, with block structures enforcing lexical nesting and lifetime management, influencing later languages' handling of scopes and garbage collection for dynamic arrays.

Historical Development

Origins as Successor to ALGOL 60

Following the publication of the report in May 1960, which introduced block structure, recursion, and lexical scoping as foundational concepts in algorithmic languages, the international community recognized the need for enhancements to address ambiguities, limited orthogonality in constructs, and gaps in features such as input/output and dynamic data handling. These shortcomings, identified through practical implementations and academic discourse, motivated the development of a successor language to extend 's principles while achieving greater generality and formal precision. The IFIP Working Group 2.1, formed in March 1962 under the International Federation for Information Processing to maintain ALGOL 60 and oversee future algorithmic languages, initiated planning for a replacement provisionally designated ALGOL X. Discussions on successor concepts began as early as 1963, building on post-ALGOL 60 symposia and implementation experiences. In May 1965, WG 2.1 convened in Princeton, United States, explicitly inviting written proposals for an ALGOL 60 successor to incorporate evolving insights into programming language design. Key proposals emerged from this call, including submissions by emphasizing pragmatic subsets, Hans Seegmüller focusing on extensions, and Adriaan van Wijngaarden advocating formal two-level grammars for syntax definition. WG 2.1 reviewed these at its October 1965 meeting in Saint-Pierre-de-Chartreuse, France, forming a subcommittee to synthesize ideas toward orthogonality—ensuring independent combination of language primitives—and a complete, machine-independent specification. This process, spanning iterative drafts from April 1966 onward, transitioned ALGOL X into by prioritizing generalization of ALGOL 60's mechanisms over mere incremental fixes, though it introduced complexities critiqued even within the group for deviating from implementability.

Design Committee and Formalization Process

The development of ALGOL 68 was led by a subcommittee of the International Federation for Information Processing (IFIP) Working Group 2.1 on Algorithmic Languages and Calculi, which had been formed in 1962 to continue support for ALGOL 60 and explore successors under the code name ALGOL X. Following the completion of ALGOL 60 revisions around 1965, the group shifted focus to designing a more advanced language, with Adriaan van Wijngaarden of the Mathematical Centre in Amsterdam emerging as a pivotal figure through his proposal for a formal syntax definition mechanism. The core design team, responsible for drafting the language report, included van Wijngaarden (Netherlands), B.J. Mailloux and J.E.L. Peck (Canada), C.H.A. Koster (Netherlands), M. Sintzoff (Belgium), C.H. Lindsey (United Kingdom), L.G.L.T. Meertens (Netherlands), and R.G. Fiskerstrand (Norway). This international group, drawing from European and North American expertise, emphasized orthogonality in language features—allowing independent combination of constructs without special cases—and rigorous formalization to eliminate ambiguities present in ALGOL 60's informal description. The formalization process centered on van Wijngaarden's innovation of the two-level grammar (also known as van Wijngaarden grammar), a meta-language technique that generated a context-free grammar capable of describing ALGOL 68's context-sensitive syntax rules precisely and verifiably. This approach, first proposed in drafts around 1967, enabled a machine-checkable definition, contrasting with the narrative-style reports of prior languages and aiming for mathematical precision in specifying syntax, semantics, and pragmatics. Key milestones included iterative meetings, such as the Tirrenia conference in June 1968 and the Munich presentation of the final draft in December 1968, where van Wijngaarden's framework was adopted despite internal debates over complexity. The initial report was approved by IFIP's Technical Committee 2 and General Assembly in 1969, establishing ALGOL 68 as an official standard. A revised report, incorporating errata and clarifications authorized by an ALGOL 68 support subcommittee of WG 2.1, was published in 1975 to address implementation feedback and refine definitions without altering core features. This process highlighted tensions within the group, as some members like C.A.R. Hoare and Edsger Dijkstra resigned or issued a minority report criticizing the design's orthogonality as leading to overly permissive and error-prone constructs, though the majority endorsed the formal rigor as essential for future-proofing the language. The subcommittee's work thus prioritized empirical testability through formal methods over consensus-driven simplicity, influencing subsequent language designs despite limited adoption.

Publication and Early Standardization Efforts

The final draft of the ALGOL 68 report (document MR 100) was completed and accepted by the International Federation for Information Processing (IFIP) Working Group 2.1 (WG 2.1) during its meeting in Munich in December 1968, despite significant internal dissent. The report, edited by A. van Wijngaarden with contributions from B.J. Mailloux, J.E.L. Peck, and C.H.A. Koster, formalized the language using a two-level Van Wijngaarden grammar for syntax definition. Approval by the broader IFIP membership followed via postal vote in March 1969, establishing the document (MR 101) as the official specification issued by Mathematisch Centrum in Amsterdam in February 1969. This publication preceded its appearance in Numerische Mathematik, volume 14, issue 2, pages 79–218, dated December 1969. Opposition to the report's publication arose from concerns over its complexity and the opacity of the metagrammar, leading to resignations from WG 2.1 by key figures including Peter Naur and in May 1968 following review of an earlier draft (MR 93). A Minority Report, drafted at the Munich meeting and signed by seven dissenters—Fritz Bauer, Fraser Duncan, C.A.R. Hoare, P.Z. Ingerman, John McCarthy, Peter Naur, and Mike Woodger—argued against endorsement, citing the document's inaccessibility and potential to hinder practical adoption. Despite this, WG 2.1 proceeded with approval, viewing the orthogonal design principles as a necessary evolution beyond 's limitations, though the dissent highlighted tensions between theoretical rigor and implementability. Early standardization efforts centered on the IFIP report itself serving as the de facto international reference, with no immediate pursuit of formal ISO ratification due to the group's focus on dissemination and validation through implementations. WG 2.1 organized a TC2-sponsored conference on implementations in Munich in July 1970 to encourage practical verification and address ambiguities. An Informal Implementers’ Interchange was established in 1969 to coordinate compiler development and report issues, laying groundwork for later clarifications. These activities underscored WG 2.1's commitment to refining the language via empirical feedback rather than immediate revisions, though they revealed challenges in achieving consensus on the specification's usability.

Language Specification

Syntax via Two-Level Van Wijngaarden Grammar

The syntax of ALGOL 68 is defined using a two-level Van Wijngaarden grammar (W-grammar), a formalism invented by Adriaan van Wijngaarden to provide a complete, formal, and extensible description of the language's structure. This approach divides the grammar into a metalevel of hyper-rules, which specify the syntax of productions using metanotions and hypernotions, and an object level of syntax clauses that generate concrete productions through recursive substitution. Metanotions, such as MODE or MOID, act as abstract categories representing syntactic entities like types or modes, enabling parametric rules that adapt to the language's orthogonal features without listing infinite cases explicitly. Hyper-rules consist of a hypernotion followed by hyperalternatives separated by semicolons, producing object-level rules via consistent replacement of metanotions with terminal forms. For example, the hyper-rule for sequences:

NOTION sequence : NOTION ; NOTION, NOTION sequence

NOTION sequence : NOTION ; NOTION, NOTION sequence

generates productions like digit cypher sequence : digit cypher ; digit cypher, digit cypher sequence when instantiated for specific notions. This mechanism allows a finite grammar to derive arbitrarily large production trees, distinguishing values, modes, and properties while enforcing context-sensitive constraints such as mode coercions and operator precedences. In the Revised Report of 1973, the W-grammar defines the entire syntax, from basic programs as strong void new closed clause to complex constructs like mode declarations (MODE ::= PLAIN ; STOWED ; REF to MODE ; ...) and format specifications (FORMAT :: structured with row of PIECE field letter aleph mode). It supports mode-independent parsing and integrates semantic elements, such as dereferencing (dereferenced to(61C) MODEi FORM : MEEK(61C) REF to MODE2 FORM), directly into syntactic rules for precision and unambiguity. The formalism's advantages lie in its ability to specify recursive, hierarchical syntax concisely, ensuring every valid ALGOL 68 program derives from finite rules while handling the language's flexibility in types, unions, and dynamic features. This contrasts with traditional Backus-Naur Form by accommodating context-dependent aspects formally, though the resulting grammar's abstraction requires systematic expansion for parser implementation.

Type System: Modes, Declarations, and Coercions

In ALGOL 68, the type system revolves around modes, which classify values according to their structure, storage requirements, and compatibility for operations. Modes encompass both primitive types, such as int for integers, real for floating-point numbers, compl for complex numbers, bool for truth values, char for characters, bits for bit patterns, bytes for byte strings, and void for the absence of value, as well as constructed types formed via declarers like references (ref), procedures (proc), arrays ([]), structures (struct), and unions (union). These primitives and constructors enable orthogonal composition, where modes can be nested or modified (e.g., long int for extended precision or flex [] real for dynamically resizable arrays), provided they form well-defined structures without infinite recursion unless shielded by ref or proc. Mode declarations introduce new mode names as abbreviations or composites of existing modes, using the syntax mode tag = declarer ;, which binds the tag within its scope without runtime elaboration. For instance, mode vector = [] real; defines a one-dimensional array of reals, while mode point = struct(real x, y); constructs a structure with two real fields accessible via selectors like x of p. Such declarations must yield equivalent modes without ambiguity, as equivalence is determined by structural comparison of mode trees, including recursive cases where cycles are permitted only if non-circular (e.g., mode node = struct(int data, ref node next);). Declarations in general, termed identity declarations, bind identifiers to values or references of specified modes via forms like mode identifier = expression ; or ref mode identifier = loc mode ;, establishing scopes where inner declarations may shadow outer ones, with uniqueness enforced per reach to avoid clashes. Collateral clauses (e.g., int a = 1, b = 2;) elaborate components in parallel, yielding a tuple unless voided. The coercion mechanism enables implicit mode adaptation in context-dependent positions, classified by strength (strong, firm, meek, weak, soft/void), to resolve type mismatches without explicit casts where compatibility holds. Six coercion kinds are defined: widening (e.g., int to real in strong contexts, as in real r = 5;), dereferencing (extracting values from ref modes, requiring non-nil references), deproceduring (invoking parameterless routines), uniting (inserting into union modes with mode indicators), rowing (converting scalars or subarrays to rows, e.g., for transput), and voiding (discarding values to void). Coercions cascade as needed during straightening, but are forbidden in firm contexts for widening or where ambiguity arises (e.g., no real to int without explicit rounding via entier or round), ensuring type safety while permitting flexible expressions like compl z = real x + i * int y;, where int widens stepwise to real then compl. Balancing in conditionals or cases promotes modes to a common supertype (e.g., int and real to real), with explicit casts via (mode) expression overriding restrictions. This system prioritizes compile-time verification over runtime checks, minimizing errors in mode conformance.

Operators, Expressions, and Assignations

ALGOL 68 operators are classified as monadic or dyadic, with monadic operators applying to a single and dyadic operators to two operands. Standard monadic operators include negation (-), absolute value (abs), and logical negation (not), while dyadic operators encompass arithmetic (+, -, *, /), relational (<, =, >), and logical (and, or) operations. Users can declare new operators through operation declarations, such as op mc = (real a, b) real: (3 * a < b | a / b), enabling overloadable and custom behaviors within specified scopes. These declarations integrate seamlessly into the language's syntax, allowing operators to be treated as procedures with parameters matching the operand modes. Operator precedence follows nine levels for dyadic operators, numbered 1 (lowest, e.g., relational operators like =) to 9 (highest, e.g., if defined), with monadic operators holding even higher precedence. Evaluation proceeds left-to-right within the same precedence level, and parentheses can override defaults, as in (x + y) * z. The syntax for dyadic formulas is primary dyadic formula, and for monadic, monad formula, ensuring unambiguous via the two-level . This system supports complex expressions without , such as abs x + y * z, where multiplication precedes addition. Expressions, termed formulas in ALGOL 68, combine units—such as identifiers, literals, or subroutine calls—with operators to yield values of specified modes. Construction involves nesting primaries and applying coercions automatically in contextual positions (strong, firm, meek, weak, or soft), which include dereferencing references, widening integers to reals, deproceduring routines to values, uniting variants, rowing arrays, and voiding in certain clauses. For instance, real(i) coerces an integer reference i via dereferencing and widening. Procedure calls within expressions, like sin(x), yield results after parameter passing and coercion, with collateral clauses enabling side effects.
Coercion TypeDescriptionExample
DereferencingConverts to valuereal(x) where x is ref real
WideningPromotes narrower mode to wider (e.g., int to real)x := 3 assigning to real variable
DeproceduringApplies procedure to yield non-procedure valuereal(random) calling a procedure
UnitingSelects from union modeUnion assignment in compatible context
Assignations generalize assignment statements into expressions using the destination := source, where destination is a reference-compatible name and source yields a value coercible to the destination's mode. Semantics require the destination to be non-nil and in scope, assigning the source's value (or multiple values for structured modes) while applying necessary coercions. Unlike imperative assignments in prior languages, ALGOL 68 assignations yield the assigned value, enabling use in larger expressions, as in y := (x := 3.14) + 1. This yields y as 4.14, demonstrating assignation's expressive role beyond mere side effects. Examples include ref int n := 0 for initialization or a[p, q] := abs y for elements.

Control and Data Structures

Procedures, Recursion, and Parameter Passing

In ALGOL 68, procedures are defined using the PROC keyword, specifying parameters in parentheses followed by an optional return mode and a colon before the body enclosed in a BEGIN...END block or similar compound statement. A procedure may yield a value of any declared mode or void, blurring the distinction between procedures and functions present in earlier languages; assignment to the procedure name within its body yields the result upon completion. For example, the syntax PROC sum = (REAL a, b) REAL: a + b; defines a procedure that returns the sum of two real parameters. Procedures support nesting, allowing inner procedures to access outer scopes, and can be declared with modes that include other procedures as parameters, enabling higher-order functions such as PROC integrate = (PROC(REAL) REAL f, REAL a, b) REAL: .... Recursion is natively supported without special syntax, as procedures can invoke themselves or mutually recurse via standard calls, leveraging the language's stack-based activation records for multiple levels. This facilitates algorithms like computation: PROC gcd = (INT n, d) INT: IF d = 0 THEN ABS n ELSE gcd(d, n MOD d) FI;. Self-referential modes, such as MODE cons = STRUCT(union(REAL, INT) value, REF cons next);, enable recursive data structures like linked lists, where procedures process them recursively, e.g., traversing a list by calling the procedure on the next field. Unlike ALGOL 60's call-by-name complications, ALGOL 68's recursion avoids macro-like expansion issues through its mode system and explicit reference handling. Parameter passing defaults to call-by-value, where actual arguments are evaluated and copied into formal parameters, preventing modification of originals unless explicitly referenced. For mutable access, formal parameters use REF mode, implementing call-by-reference by passing the location (reference) rather than value, as in PROC increment = (REF INT x) VOID: x +:= 1;. Coercions allow compatible types (e.g., INT to REAL) or dereferencing REF parameters implicitly during calls, with parameters elaborated left-to-right in a strong context for the primary and meek for void results. Restrictions apply: files and certain packed structure components cannot pass by value, and procedure parameters are value-only to avoid closure complexities. This mechanism, formalized in the 1973 Revised Report, prioritizes type safety over ALGOL 60's call-by-name, reducing evaluation order ambiguities while supporting flexible mode declarations.

Arrays, Structures, Unions, and Slices

Arrays in ALGOL 68 are declared using bounds specifiers and a base mode, supporting fixed or flexible dimensions for storing multiple values of the same mode. A one-dimensional array is specified as [lower:upper] mode, such as [1:10] int a, where bounds can be compile-time constants or variables evaluated at runtime. Multi-dimensional arrays use nested brackets, like [1:n, 1:4] int matrix, and elements are stored in row-major order. Flexible arrays employ the flex keyword, as in flex [1:0] real dynamic_array, permitting runtime resizing through assignment to compatible slices or arrays. Subscripting accesses elements via indices, yielding values or references depending on context, e.g., a[i] := value for assignment. Structures aggregate fields of potentially differing modes into a composite type, declared as struct (field1 mode1, field2 mode2) struct_mode. For example, mode point = struct (real x, y); point p = (1.0, 2.0) defines and initializes a with named fields accessible via selectors like x of p. Fields can include primitives, arrays, or nested structures, and selectors yield subvalues or subnames for further operations. Structures support assignment of matching values, with fields updated component-wise, and are straightened in declaration order during input/output. Unions enable a single variable to hold values from alternative modes, declared as union (mode1, mode2, ...) union_mode, such as union (int, real) variant = 42 or variant := 3.14. Access requires runtime type determination via case clauses, e.g.,

case variant in (int i: print(i); real r: print(r)) esac

case variant in (int i: print(i); real r: print(r)) esac

to handle the active mode safely, as unions maintain an implicit tag for type conformity. Direct operations on untagged unions are restricted to prevent type errors, enforcing through mode checking. Unions cannot be flexibly dimensioned in subsets like ALGOL 68S and are excluded from standard input/output routines due to type ambiguity. Slices, or trims, extract contiguous subarrays as first-class values, generalizing subscripting with range notation like array_slice[lower:upper]. For instance, in a declared array u[1:n] real, u[2:5] yields a slice equivalent to (u[2], u[3], u[4], u[5]) with bounds [1:4] relative to the slice, supporting assignment such as flex [1:4] real temp := u[2:5]. Multi-dimensional slices select rows, columns, or volumes, e.g., matrix[i, ] for the i-th row or matrix[ , j1:j2] for a column segment, with collateral evaluation of indices. Slice bounds are revisable, allowing overlapping or dynamic subsets, and slices conform to array modes for operations like whole-array assignment. Bounds inquiries via lwb and upb apply to slices, e.g., upb(u[2:5]) returns 4.

Control Flow and Compound Statements

In ALGOL 68, is primarily managed through a of that unify concepts from prior languages, such as blocks, compound statements, and conditional expressions, into serial for sequential execution. A serial consists of a sequence of units (executable constructs) separated by semicolons, optionally preceded by declarations or labels, and yields the value of its final unit unless terminated early by an exit or jump. This structure establishes a new environment (environ) for scoping and enables serial composition of actions, where completion of one unit triggers the next. Serial clauses can function as expressions, statements, or blocks, providing flexible compounding without explicit begin-end delimiters in many cases, though parentheses or loop delimiters like do...od may enclose them. Conditional execution employs conditional clauses, which select between alternatives based on a enquiry. The syntax is if condition then unit [else unit] fi or equivalently condition | unit | unit, where the condition evaluates to true or false, executing the corresponding unit and yielding its result; the else branch is optional, defaulting to a void unit if omitted. Multiple alternatives can chain via elif forms, but the core mechanism ensures balanced selection with firm evaluation of the chosen path. Semantics enforce that the enquiry is evaluated once, with the selected unit's environ activated, supporting nested declarations and side effects within branches. Selection for multiple discrete choices uses case clauses, generalizing conditionals for integral values or mode matching. The form is case integral-expression in unit {, unit} [out unit] esac, where the expression's value k (an integer from 1 to the number of units) selects the k-th unit for execution; an optional out clause handles unmatched values, and mode-based selection applies if the expression conforms to unit modes. If no match occurs or multiple modes fit ambiguously, behavior is undefined, emphasizing the need for exhaustive, non-overlapping cases. This construct yields the selected unit's value and integrates seamlessly with serial compounding for multi-way branching. Iteration relies on loop clauses, including for and while variants. A for clause iterates as for identifier [from lower] [by step] [to upper] [while condition] do unit od, binding the identifier to successive values from lower (default 1) to upper inclusive, incrementing by step (default 1), and executing the unit each until bounds exceed or the while condition fails; the loop establishes a dynamic environ per , allowing identifier reuse without redeclaration. The while clause, while condition do unit od, tests the condition before each repetition, executing the unit only if true and yielding void upon exit. Both support early termination via exits or jumps and compound multiple statements within the do...od serial . Unstructured control permits go to statements for explicit jumps: go to label, transferring execution to a labeled unit (declared via label name:), terminating the current serial clause and potentially yielding a routine in procedural contexts. Labels are scoped to environs, and jumps across nested scopes alter abruptly, contrasting the language's preference for structured clauses but allowing necessary flexibility for error handling or optimization. Compound statements, inherently serial clauses, avoid goto proliferation by nesting units hierarchically, with semantics ensuring sequential elaboration unless interrupted.

Specialized Features

Input/Output: Transput Mechanisms

In ALGOL 68, input and output operations are collectively termed transput, encompassing mechanisms for transferring data between program variables and external media such as terminals, files, or devices. This system addresses limitations in prior languages like ALGOL 60 by providing structured, flexible handling through predefined modes and procedures in the standard environment, enabling both sequential and random access while maintaining machine independence for core operations. Transput relies on three primary modes: book, representing a collection of text structured as flexible arrays of pages, lines, and characters; channel, defining communication pathways to devices (e.g., predefined stand in channel for input and stand out channel for output); and file, a structure associating a book with a channel, managing position (page, line, character) and state for data transfer. Files are established via procedures like open, which links a file to a book identifier and channel (e.g., open(loc file f, "input.dat", stand in channel)), and close to terminate access, with options for creation, locking, or scratching files. Buffering is supported by associating files with character arrays acting as pseudobooks (e.g., associate(f, [1:80] char buffer)), allowing overflow handling and direct memory transput. Position control enables random access via set (e.g., set(f, page 1, line 10, char 1) after verifying possible(f)), while layout procedures like newline, newpage, space, and backspace manage output positioning independently of data transfer. Unformatted transput performs direct, formatless data transfer using procedures such as get and put for files or channels, and read and print for values, skipping whitespace and newlines as needed while supporting multiples and structures. For instance:

print((x, newline)); # Outputs value of x followed by a newline[](https://inria.hal.science/hal-03027689/file/Lindsey_van_der_Meulen-IItA68-Revised.pdf) read((y, z)); # Inputs values into y and z sequentially[](https://pkeus.de/~wb/RR/tanenbaum.pdf) get(stand in file, (s, newline)); # Reads a string s and newline from standard input[](https://www.softwarepreservation.org/projects/ALGOL/report/Algol68_revised_report-AB-600dpi.pdf)

print((x, newline)); # Outputs value of x followed by a newline[](https://inria.hal.science/hal-03027689/file/Lindsey_van_der_Meulen-IItA68-Revised.pdf) read((y, z)); # Inputs values into y and z sequentially[](https://pkeus.de/~wb/RR/tanenbaum.pdf) get(stand in file, (s, newline)); # Reads a string s and newline from standard input[](https://www.softwarepreservation.org/projects/ALGOL/report/Algol68_revised_report-AB-600dpi.pdf)

These operate in a firm context, dereferencing references without widening, and handle end-of-file via event routines like on logical file end. Formatted transput extends this with precise control via getf, putf, readf, and printf, employing format texts delimited by $...$ to specify patterns for alignment, width, precision, and literals, matching data to input streams or generating output layouts. Patterns include frames like d for digits, g for general formatting, and qualifiers (e.g., +3d for signed 3-width integer, 12zde for real with zone filling). Examples include:

printf(($+3d x 3d$, 123, 456)); # Outputs " 123 456" with alignment[](https://pkeus.de/~wb/RR/tanenbaum.pdf) readf((&#36;3d$, i)); # Reads exactly 3 digits into integer i[](https://inria.hal.science/hal-03027689/file/Lindsey_van_der_Meulen-IItA68-Revised.pdf) putf(out file, ($g$, name)); # Outputs string name in general format to file[](https://www.softwarepreservation.org/projects/ALGOL/report/Algol68_revised_report-AB-600dpi.pdf)

printf(($+3d x 3d$, 123, 456)); # Outputs " 123 456" with alignment[](https://pkeus.de/~wb/RR/tanenbaum.pdf) readf((&#36;3d$, i)); # Reads exactly 3 digits into integer i[](https://inria.hal.science/hal-03027689/file/Lindsey_van_der_Meulen-IItA68-Revised.pdf) putf(out file, ($g$, name)); # Outputs string name in general format to file[](https://www.softwarepreservation.org/projects/ALGOL/report/Algol68_revised_report-AB-600dpi.pdf)

Unlike unformatted transput, formatted modes enforce strict matching, support insertions for literals, and allow complex layouts via metanotions like fpattern for dynamic specification, though they require compatible input/output modes (e.g., integral or real). Event handling, such as on format error, ensures robustness during mismatches or overflows.

Parallel Processing with 'par'

ALGOL 68 provides facilities for parallel processing via the par keyword, which designates a parallel clause by prefixing a collateral clause, thereby requiring the simultaneous elaboration of its units as distinct . The involves par followed by a comma-separated sequence of units, optionally enclosed in parentheses or a begin-end block, such as par (unit1, unit2) or par begin unit1; unit2 end. Execution semantics mandate that all units commence concurrently, with the parallel clause yielding control only after every unit has completed, ensuring no partial results from unfinished . This model supports essential concurrent programming but relies on hardware and support for actual parallelism, as the language specification leaves scheduling and to the implementer. In contrast to serial clauses, which execute units sequentially via semicolons, and collateral clauses, which elaborate units simultaneously without enforced concurrency or process separation (permitting optimizer discretion on order and allowing composite stowed yields like tuples), parallel clauses enforce concurrency while yielding void and prohibiting stowed value composition. Collateral elaboration occurs in contexts like evaluation or initializers, such as [1:4] real x := (f(1), f(2), f(3), f(4)), where functions may run in undefined order for efficiency, but parallel clauses introduce explicit boundaries. Shared environments persist across units, necessitating explicit to mitigate race conditions from side effects on common variables. Synchronization employs semaphores of mode sema, initialized via level n (where n is a non-negative integer), with down (wait if level below 1, then decrement) and up (increment) operators for mutual exclusion or signaling. For instance, a mutex might be declared as sema mutex = level 1, with units performing down mutex before critical sections and up mutex after. A producer-consumer example illustrates bounded buffers:

sema free_slots = level buffer_size; sema full_slots = level 0; sema mutex = level 1; par begin while true do down free_slots; down mutex; buffer[index] := produce(); index +:= 1; up mutex; up full_slots od end, begin while true do down full_slots; down mutex; consume(buffer[index]); index -:= 1; up mutex; up free_slots od end end

sema free_slots = level buffer_size; sema full_slots = level 0; sema mutex = level 1; par begin while true do down free_slots; down mutex; buffer[index] := produce(); index +:= 1; up mutex; up full_slots od end, begin while true do down full_slots; down mutex; consume(buffer[index]); index -:= 1; up mutex; up free_slots od end end

This coordinates production and consumption, preventing overflows or underflows. Without synchronization, unsynchronized accesses yield , as merging of actions in time lacks a prescribed order. The Revised Report, finalized in with errata through , limits parallelism to these basics due to contemporary hardware constraints, omitting advanced features like dynamic process creation. Many implementations, such as ALGOL 68-R () and ALGOL 68S subsets, omit or simulate par sequentially for single-processor compilation simplicity, restricting full concurrency to multiprocessor environments like certain systems. Scope rules confine parallel units to the enclosing environment's layer, with no new lexical scopes unless explicitly layered, preserving identifier visibility while demanding disciplined sharing.

Pragmatics, Comments, and Program Representation

In ALGOL 68, , referred to as pragmats or praments, provide mechanisms for implementation-specific directives or hints that extend beyond the core language semantics, such as optimizations, assertions, or control over actions like compilation phases not expressible in standard programs. These are syntactically defined as sequences initiated and terminated by pragmatics symbols (e.g., pr ... pr), often restricted in contexts like format texts to avoid interference with , and carry no defined semantics in the standard, allowing implementations to process or ignore them as needed. For instance, a pragmat might assert preconditions via pr assert condition pr, influencing runtime checks or code generation without altering program elaboration. Comments in ALGOL 68 serve solely for human-readable annotations, excluded from execution and beyond delimitation. Their syntax follows comment ::= comment-symbol style-comment-text end-comment-symbol, where the comment-symbol can be co or boldface CO, and the end-symbol ed or boldface ED, with the style-comment-text comprising arbitrary glyphs or nested praments but no semantic impact. In representation languages, these delimiters may appear as special characters like ¢ for the symbol and c for termination, ensuring comments are stripped during without affecting tokenization. Non-printing characters and blanks within comments are insignificant, mirroring treatment elsewhere except in strings, and comments may nest or include pragmatics, though implementations typically flatten them for processing. Program representation in ALGOL 68 employs a layered approach via representation languages—reference (canonical for specification), publication (typographically enhanced), and hardware (machine-oriented)—to encode strict-language programs as sequences of basic symbols, worthy characters, and newlines. The reference language mandates typographical distinctions, such as boldface for mode symbols (e.g., int) and italics for variables (e.g., x), with blanks insignificant outside strings or comments to permit flexible spacing; where bold or italic is unavailable, conventions like underlining or uppercase suffice for portability. A complete program derives from the production program ::= strong void new closed clause, elaborated in a primal environment, with praments and comments integrated as tokens preceding symbols, ensuring parse independence from modes while supporting efficient implementation mapping to hardware representations.

Implementations and Variants

Early Compilers and Interpreters (1968-1980s)

The initial report on ALGOL 68 was published in December 1968, prompting immediate implementation efforts despite the language's complexity, which included advanced features like and two-level that complicated . An IFIP Working on ALGOL 68 Implementation, held in from July 20-24, 1970, served as a key forum for sharing progress, revealing ongoing work across and highlighting the need for practical subsets to address full-language challenges such as and . The first operational compiler, ALGOL 68-R, emerged from the Royal Radar Establishment (RRE) in Malvern, , as a subset implementation operational by mid-1970, targeting ICL 1900 series mainframes with a 64-character set that required adaptations like bold stropping for mode indicators and operators. Written initially in an extended dialect, it prioritized core features while omitting some advanced ones like parallel clauses to enable feasibility on hardware of the era, and it gained traction in universities throughout the 1970s for teaching and research. In the United States, ALGOL 68C, developed circa 1970, produced portable ZCODE intermediate output interpretable or compilable to native code, facilitating deployment on diverse systems including early Unix environments at by the mid-1970s, where it supported tasks. Efforts at Carnegie-Mellon University and the also yielded compilers in the early 1970s, often tailored for specific operating systems and emphasizing semantic analysis passes to handle ALGOL 68's mode coercion rules. European implementations followed, with a full-language compiler from CDC Netherlands delivered in 1977 for CDC mainframes, driven by academic demand and supporting the complete revised report including transput and parallelism. In the , early compilers appeared in the late , such as one developed in Kiev for hardware, reflecting state-directed computing research amid limited Western access. These efforts, predominantly compilers rather than interpreters due to performance needs on contemporary hardware, demonstrated ALGOL 68's viability but underscored implementation hurdles like multi-pass processing for its abstract syntax trees, with subsets like ALGOL 68-R proving more practical initially.

Subsets and Extensions like ALGOL 68-R

ALGOL 68-R, developed by the Royal Radar Establishment in the , represented an early practical subset of the full ALGOL 68 language, implemented as a to facilitate deployment on hardware like the ICL 1900 series. Released in based on the late-1968 draft report, it introduced modifications such as requiring all variables to be declared before their first use, which simplified compilation while maintaining core features like strong typing and . This subset omitted certain advanced constructs from the full specification to prioritize implementability, enabling the first working ALGOL 68 compiler despite the language's syntactic and semantic complexities. Another notable subset, ALGOL 68S, served as the official IFIP-recognized restricted dialect designed explicitly for one-pass compilation, emphasizing numerical and scientific applications where full language features were deemed unnecessary. It excluded elements like dynamic semantics and certain mode conversions present in the complete ALGOL 68, focusing instead on static analysis for efficiency in teaching and prototyping environments. Implementations often extended ALGOL 68S slightly for portability across systems, but retained its core restrictions to avoid the runtime overhead of the full language's flexibility. Extensions to subsets like ALGOL 68-R included ALGOL 68-RT, which added multithreading support via the ICL 1900's subprogramming capabilities, allowing parallel execution of program segments without altering the base subset's structure. These variants addressed real-world deployment needs by balancing the original language's expressiveness with hardware constraints, influencing later dialects such as ALGOL 68RS for specific runtime systems. Overall, subsets prioritized verifiable compilation over exhaustive feature coverage, enabling adoption in environments where full ALGOL 68 proved prohibitive due to its formal rigor.

Modern Implementations and Recent Revivals (2000s-2025)

In the , open-source efforts preserved and extended ALGOL 68 through portable implementations, driven by academic and enthusiast interest in its advanced features like strong typing and . The Algol 68 Genie (a68g), developed by Marcel van der Veer, emerged as a key compiler-interpreter, offering a nearly complete implementation of the Revised Report language, including support for , complex numbers, parallel processing via the par construct, and transput for input/output. Released under the GNU General Public License, it targets modern platforms such as , Windows, and macOS, with versions like 2.5.2 from 2014 emphasizing portability and runtime efficiency through C backend generation. Complementing Genie, the Algol68G interpreter, also hosted on SourceForge, provides an accessible runtime environment for experimentation, running on Windows, macOS, and without requiring compilation setup. Maintained by Neville Duncan, it supports core ALGOL 68 syntax and semantics, facilitating code execution for educational purposes and small-scale applications. These tools, active through the , reflect a niche revival focused on fidelity to the original specification rather than commercial adoption. Recent developments in the 2020s signal renewed engineering interest, particularly in integrating ALGOL 68 with contemporary toolchains. In January 2025, Oracle engineer Jose E. Marchesi proposed patches for a GA68 front-end to the GNU Compiler Collection (GCC), aiming to compile ALGOL 68 directly to machine code via GCC's infrastructure, including support for recursion, unions, and mode declarations. Despite initial review hurdles, development persisted into October 2025, with demonstrations of compilable examples and potential for cross-platform binaries. Concurrently, enhancements to GNU Marst—a translator converting ALGOL 68 to C—reached version 2.8 in 2025, enabling legacy code migration while preserving semantic intent, as part of broader efforts to modernize pioneer languages for analysis and reuse. These initiatives, though limited to specialized communities, underscore ALGOL 68's enduring appeal for research into expressive, formally defined languages, contrasting with the dominance of simpler paradigms in mainstream software. No widespread industrial revival has occurred, but open-source repositories and mailing lists sustain discussion and incremental improvements.

Applications and Examples

Systems Programming and Operating Systems

ALGOL 68's inclusion of low-level data modes such as bits, bytes, and machine-specific representations, combined with facilities for dynamic allocation and procedure-valued expressions, positioned it for tasks requiring both and hardware proximity. Implementations like ALGOL 68-R extended these with mechanisms for inline code insertion and direct access to runtime variables via patch instructions, facilitating efficient systems-level code without resorting to assembly. These features supported modular of complex software, as demonstrated in environments where ALGOL 68 variants handled and processing under multiprogramming OSes like GEORGE 3 on ICL 1900 series hardware. A prominent application occurred in the CAP project, where operating system—a capability-based design emphasizing secure resource protection—was developed using ALGOL 68C starting in 1971. The language's strong typing and orthogonal mode unions enabled implementation of kernel primitives for capabilities, with the ported to CAP's custom hardware to manage segmented and protection domains. This effort highlighted ALGOL 68's viability for OS kernels in research settings, though performance tuning relied on optimizations for the transputer-like . Commercially, the ' VME operating system, operational from the mid-1970s, was predominantly coded in S3—a structured, imperative derived from ALGOL 68-R with hardware-mapped aggregates for efficient segment handling and I/O control. S3's syntax and semantics, including parallel clauses adapted from ALGOL 68's par construct, supported VME's abstraction and executive functions across mainframe configurations. Such uses underscored ALGOL 68 derivatives' role in production OSes, prioritizing reliability over the raw speed of lower-level alternatives, though adoption remained confined to vendor-specific ecosystems.

Scientific Computing and Other Uses

The Numerical Algorithms Group (NAG) developed a dedicated ALGOL 68 library for numerical computing, with released in March 1976 for ICL 1900 series machines, eventually encompassing four marks and supporting algorithms for integration, differential equations, linear algebra, and statistical analysis. This library facilitated scientific applications on university computers, providing well-documented routines that researchers could integrate into custom programs for computational tasks in and . Despite its capabilities, adoption remained limited compared to Fortran-based alternatives, as ALGOL 68's complexity hindered widespread use in high-performance numerical environments. ALGOL 68 supported through extensions like A68SIM, which leveraged the language's strong typing and procedural features to model complex systems without relying on specialized languages. For instance, in 1976, ALGOL 68/R was used to develop models for multi- tracking feasibility studies, enabling iterative modeling of and in defense research. These applications demonstrated ALGOL 68's suitability for algorithmically intensive simulations requiring precise control over data structures and parallel constructs, though practical deployment often favored simpler languages for production-scale runs. Beyond core numerical work, ALGOL 68 found niche applications in and graphical processing, as in the GRAPHEX68 system, which exploited user-defined modes and operators to manipulate vector-based pictures for engineering design visualization. It also underpinned hardware description tools like ELLA, developed by the UK's Royal Signals and Radar Establishment in the 1980s–1990s, where ALGOL 68's abstract data types aided in simulating digital circuits and at the . Such uses highlighted the language's flexibility for domain-specific extensions in scientific visualization and embedded systems prototyping, albeit in specialized research settings rather than commercial software.

Illustrative Code Samples

A basic output program in ALGOL 68, demonstrating transput with the print procedure and format items, is as follows:

algol68

begin print (("Hello, World!", newline)) end

begin print (("Hello, World!", newline)) end

This closed clause elaborates the print statement, directing output to the standard channel via a tuple of a string literal and the predefined newline item. Mode declarations enable user-defined types, such as a recursive structure for linked data:

algol68

mode book = struct (string text, ref book next); book first = ( "Chapter 1", nil );

mode book = struct (string text, ref book next); book first = ( "Chapter 1", nil );

The struct mode combines a string field with a reference to another book, supporting dynamic list construction; nil denotes the absence of a reference. Procedures encapsulate computations with typed parameters and returns, as in this trigonometric function:

algol68

proc ncos = (int i, int n) real: cos (2 * pi * i / n); real result = ncos (1, 360);

proc ncos = (int i, int n) real: cos (2 * pi * i / n); real result = ncos (1, 360);

The procedure takes integer indices, computes a normalized cosine, and exemplifies coercion from int to real in arithmetic expressions. Parallel elaboration via collateral clauses allows concurrent execution, with semaphores for :

algol68

sema mouth = level 1; par begin do down mouth; eat; up mouth od, speak end

sema mouth = level 1; par begin do down mouth; eat; up mouth od, speak end

This snippet models producer-consumer , where down and up adjust semaphore levels to prevent concurrent access to shared resources like mouth. Unions provide variant types for flexible data representation:

algol68

union (bool, char) t; t := true; t := 'a';

union (bool, char) t; t := true; t := 'a';

The variable t holds either a bool or char value, with assignments triggering dynamic type checks during elaboration.

Criticisms and Limitations

Over-Engineering and Complexity Issues

ALGOL 68's design emphasized —allowing independent combination of features—and completeness, aiming to handle all computational scenarios without exceptions, but this resulted in a proliferation of modes, generators, and transformations that overwhelmed practical application. The mode system, which generalized types to include dynamic aspects like flexibility and parallelism, required intricate mode during compilation, often involving a complex graph of implicit coercions that could span dozens of potential conversions, making error detection and optimization challenging. This generality, while theoretically sound, prioritized expressiveness over simplicity, leading to constructs like the "unites" for variant types and "parallel" clauses that introduced runtime overhead and debugging difficulties not present in more restrained predecessors like ALGOL 60. Committee-driven development exacerbated over-engineering, as compromises among diverse contributors introduced to accommodate varying priorities, such as extensive parallel processing support and abstract storage mechanisms, without redundancies. The resulting syntax and semantics demanded familiarity with non-standard terms like "stropping" for keyword delimitation and "vanish" modes for conditional execution, which hindered adoption by increasing the for programmers accustomed to procedural clarity. Internal debates during finalization highlighted this, with some members decrying the shift from ALGOL 60's elegance to a framework laden with orthogonal extensions that prioritized formalism over . Implementation efforts underscored these issues, as the language's ambition for formal semantic rigor—detailed in a report exceeding 300 pages—complicated parser generation and type checking, with early compilers struggling against the of mode unions and environment inquiries. Critics noted that while subsets like mitigated some burdens by restricting features, the core design's insistence on universality deterred widespread tool development, reinforcing perceptions of the language as intellectually ambitious yet pragmatically unwieldy.

Formalism's Practical Drawbacks

The two-level van Wijngaarden grammar employed in ALGOL 68's specification enabled a highly precise, context-sensitive definition of syntax and semantics, but this formalism proved burdensome for writers. Unlike context-free grammars amenable to efficient algorithms like or LR, the metalinguistic constructs required generating hyper-rules and proto-rules to derive valid productions, demanding custom meta-tools or manual simulation that exceeded the computational and expertise resources typical in the 1970s. Early implementers frequently simplified to one-pass or subset compilers, such as ALGOL 68-R released in 1969, to circumvent full grammar complexity, as evidenced by conference papers documenting ambiguities and undecidability risks without restrictions. The syntax's reliance on mathematical notation, including boldface modes (e.g., real) and diacritical operators, further exacerbated input and output challenges on ASCII-limited hardware. The 1973 Revised Report introduced "indicant" alternatives like [] brackets for bold symbols to facilitate terminal entry, yet these transliterations increased cognitive load for programmers, fostering errors in declaration and operator precedence while deviating from the formal ideal of unambiguous readability. This typographical formalism prioritized theoretical purity over ergonomic practicality, contributing to sparse tool ecosystems and limited debugging support in production environments. Semantically, the orthogonal design principles—allowing arbitrary combinations of modes, coercions, and parallel clauses—interacted in ways the formal notation inadequately constrained, leading to implementation variances and runtime inefficiencies. For instance, strong typing with automatic coercions, while formally defined, imposed overhead in memory management and evaluation order, complicating optimization on hardware like the ICL 1900 series where initial compilers ran. These factors delayed full-featured compilers until the , with most deployments relying on interpretive modes or dialects that sacrificed formalism for usability, underscoring a core tension between algebraic rigor and deployable engineering.

Dissents from Key Figures like Dijkstra and Hoare

C. A. R. Hoare, a key contributor to , issued a "Critique of ALGOL 68" in the ALGOL Bulletin in November 1968, shortly after the language's revised report. In it, he outlined principles for effective language design, including extreme simplicity with a minimal set of structurally simple features and high efficiency in translating to compact machine code akin to . Hoare objected to ALGOL 68's self-extension mechanisms for lacking operator priorities and right association, complicating intuitive use, and to its nucleus for inefficient array handling, overly elaborate mode conversions, and informal reference scoping that obscured enforcement. Edsger W. Dijkstra, who had praised ALGOL 60's elegance, voiced strong reservations in a December 1968 letter to the ALGOL Bulletin editor, describing the ALGOL 68 draft as "grim reading" due to the "size and complexity of the defining apparatus." He argued that the language's conception resisted more concise or transparent definition, rendering error detection from its "thick and difficult" document improbable and a convincing absence of pitfalls unattainable. Dijkstra warned that proceeding would lead WG2.1 into a "dead alley," recommending outright rejection or substantial revision over minor fixes. Hoare and Dijkstra co-signed a minority report attached to the ALGOL 68 report in 1968, labeling the effort an "experiment which had failed" and unfit as a tool for reliable programming. In his 1980 Turing Award lecture, Hoare reflected on the meeting's overambition, recounting his unheeded warnings against the design's obscurity and features like predominance of references and added without full understanding, noting that such inclusions become irrevocable. He deemed ALGOL 68 "part of the problem rather than part of its solution," exemplifying designs so complicated that deficiencies evade obvious detection.

Legacy and Reception

Influence on Later Programming Languages

ALGOL 68's emphasis on —allowing independent combination of language features without undue restrictions—influenced the design of subsequent languages seeking flexible abstraction. Its mode system, enabling strong static typing with user-defined types and coercions, provided a foundation for advanced type mechanisms in later imperative languages. For example, Ada adopted principles of and modular decomposition partly inspired by ALGOL 68's approach to data structuring and , though Ada's committee simplified syntax to mitigate compilation challenges observed in ALGOL 68 implementations. The language's syntactic innovations, including user-defined operators and flexible declarations, directly impacted C and its derivatives. Keywords such as void, struct, union, long, and short in C trace origins to ALGOL 68's lexicon, facilitating structured data handling in systems programming. Bjarne Stroustrup, C++'s designer, explicitly drew ideas from ALGOL 68, including its procedural semantics and type-rich environment; he described his early vision for C++ as "ALGOL 68 with classes" rather than an extension of C alone. Conversely, ALGOL 68's complexity prompted simplifying reactions in languages like Pascal. , involved in ALGOL discussions, rejected ALGOL 68's elaborate features—such as its two-level grammar and extensive flexibility—in favor of Pascal's restrained structure for teachability and reliability, yet retained core block-structured paradigms and added explicit pointers to extend applicability beyond ALGOL 68's scope. This dialectic influenced Wirth's later languages, which incorporated modules for better modularity while preserving simplicity. ALGOL 68's parallel execution clauses also foreshadowed concurrency primitives in languages like Occam, emphasizing synchronization via semaphores and priorities. Overall, while not widely implemented commercially, ALGOL 68's conceptual contributions persist in modern languages' handling of types, operators, and concurrency.

Reasons for Commercial Failure and Academic Persistence

ALGOL 68's commercial failure stemmed primarily from its excessive complexity, which arose from an orthogonal design principle that prioritized theoretical generality over practical usability, resulting in features like multiple forms of coercion (deproceduring, dereferencing, uniting, widening, , and voiding) and infinite modes that proved burdensome to implement and use. The language's syntax, defined via van Wijngaarden grammars, required multi-pass compilers—often four or more—and context-sensitive parsing that challenged early implementers, with many university efforts failing and full compilers not emerging until the late , such as the CDC implementation in 1977. This delayed availability meant that by the time viable systems existed, industries had already committed to established alternatives like for scientific computing and for business applications. Compounding these technical hurdles were flaws in documentation and the committee-driven development process, which involved over a dozen contributors and led to a 1968 draft report criticized for obscurity and non-standard terminology, prompting resignations from key figures including and . A Minority Report signed by eight IFIP 2.1 members, including Edsger Dijkstra and Hoare, deemed the language a failure due to its loss of 60's simplicity and over-complexity. The absence of standardized input/output further eroded portability, as implementations relied on vendor-specific extensions, deterring adoption in commercial environments where reliability and interoperability were paramount. The timing of ALGOL 68's finalization exacerbated its marginalization; the original report appeared in 1968, with a delayed until 1975 amid and subcommittee disputes, by which point simpler rivals had gained traction—Pascal in 1970 as Wirth's rejected alternative proposal, and in 1972, aligned with Unix's rise on Unix-compatible systems. Fortran's IBM-backed dominance in scientific domains and COBOL's entrenchment in enterprise further limited , as ALGOL 68 lacked the support or simplicity to displace incumbents. Despite commercial neglect, ALGOL 68 persisted academically due to its pioneering contributions to type systems, strong typing, and , which influenced subsequent languages including Pascal's structured constructs, Ada's package mechanisms, and C's array handling and user-defined operators. Its emphasis on formality and provided a foundation for , with ongoing academic implementations and teaching use in regions like the (e.g., on ICL systems) and the , where it informed design and formal semantics research. Even critics acknowledged its innovations, sustaining interest in its ideas for advanced language features long after industrial irrelevance.

Contemporary Interest and Potential Future Relevance

Despite its historical commercial limitations, ALGOL 68 maintains niche interest among programming language enthusiasts and preservationists, evidenced by active open-source implementations such as Algol 68 Genie, which supports features like and parallel processing on modern platforms. This implementation, updated as recently as 2023, enables experimentation with the language's orthogonal design and strong typing in contemporary environments. In 2025, developer Jose E. Marchesi proposed and continues to refine a front-end for ALGOL 68 within the GNU Compiler Collection (GCC), integrating it with modern toolchains for x86 and other architectures. This effort, building on initial patches submitted in January 2025, aims to facilitate compilation of ALGOL 68 code alongside other languages in GCC, potentially aiding legacy system maintenance or exploratory projects valuing its mode analysis and coercion rules. Such developments reflect a small but persistent community drive to render the language viable on current hardware, as highlighted in exploratory articles and tutorials from 2020 onward. Potential future relevance lies in educational contexts for studying advanced type systems and formal semantics, concepts that influenced later languages like Ada and Modula-2, though widespread adoption remains improbable due to syntactic complexity and competition from more pragmatic alternatives. Preservation projects, including YouTube series on "modern programming with Algol 68" launched in June 2025, underscore its role in historical computing retrospectives rather than mainstream application. Niche uses in domains requiring rigorous specification, such as hardware description or scientific computing prototypes, could emerge if GCC integration matures, but empirical evidence of broad revival is absent as of October 2025.

References

Add your contribution
Related Hubs
User Avatar
No comments yet.