Bold symbols and reserved words 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 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 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 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 ALGOL 68 has a hierarchy of contexts which determine the kind of coercions available at a particular point in the program. These contexts are: For more details about Primaries, Secondaries, Tertiary & Quaternaries refer to
Operator precedence.
pr & co: Pragmats and Comments 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 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 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:
proc: Procedures 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 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 These are technically not operators, rather they are considered "units associated with names"
Monadic operators Dyadic operators with associated priorities Specific details: • Tertiaries include names
NIL and ○. •
LWS: In Algol68
r0 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 ''''''
Assignation and identity relations, etc. These are technically not operators, rather they are considered "units associated with names" Note: Quaternaries include names
SKIP and ~. (alternatively ) tests if two pointers are equal; (alternatively ) tests if they are unequal.
Why and are needed 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 , and compare those, since the operator is defined for , but not . It is
not legal to define for operands of type and at the same time, because then calls become ambiguous, due to the implicit coercions that can be applied: should the operands be left as and that version of the operator called? Or should they be dereferenced further to 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 , 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 : 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 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 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 "Formatted transput" in ALGOL 68's transput has its own syntax and patterns (functions), with
FORMATs embedded between two $ characters. 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 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 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==