[RFC,V2] GNU Algol 68 Coding Guidelines

jpl jpl.algol68@gmail.com
Tue Jan 13 20:57:55 GMT 2026


Some extremely small wordings and spelling changes.  So small, I feel
guilty even sending this mail.  /James

> New version, with some typos and some additional contents added based on
> the feedback received so far..
>
> ---
>     _    __    ___
>    / \  / /_  ( _ )
>   / _ \| '_ \ / _ \           GNU Algol 68 Coding Guidelines
>  / ___ \ (_) | (_) |
> /_/   \_\___/ \___/
>
>
>
>
>                                                       Jose E. Marchesi
>                                                        January X, 2026
>
>
>           Please send suggestions and proposals related to
>           this document to algol68@gcc.gnu.org
>
>
> This document contains a set of conventions and recommendations for
> writing Algol 68 code which is part of ga68, the GNU Algol 68
> compiler. As with any coding conventions, the goal is to achieve a
> coherent style among the codebase.
>
> Algol 68 is probably the programming language with the most carefully
> and lovingly designed syntax ever made.  It can be verbose when it is
> convenient for the programmer, and also extremely compact while
> keeping an astounding high level of readability.  These conventions
> aim to make a good use of that.
>
> Feel free to adopt our guidelines for your own Algol 68 project,
> partially or entirely.
>
> In what follows we make extensive use of Algol 68 terminology, which
> may be confusing at first for the uninitiated reader.  The Algol 68
> Jargon File provides definitions for many of the terms used in the
> context of the Algol 68 programming language and associated
> technologies.  If you find yourself wondering about "frobyts" or
> "enclosed clauses", please look them up in the jargon file.  The file
> is available online in the www and, in Gentoo, as manpages once you
> install the app-doc/a68-jargon package. Just type `man 7algol frobyt'
> in the terminal, for example.
>
> => https://jemarch.net/a68-jargon The Algol 68 Jargon File
>
> Additionally, in this document we use the term "space" and "spaces" to
> refer to "typographical display features", i.e. spaces, tabs and
> newlines.  These characters are of no significance and do not alter
> the meaning of the program when they appear between symbols, outside
> of string and character denotations, but they have a great impact on
> the readability of the code and are the main tool for formatting.
>
> ## Stropping
>
> The GNU Algol 68 compiler supports two stropping regimes:
>
> * The "classic" UPPER stropping, which is one of the standard
>   stropping regimes defined in the Standard Hardware Representation
>   for Algol 68.  This regime uses upper-case letters to encode bold
>   letters and lower-case letters to encode non-bold letters.
>
> * The "modern" SUPPER stropping, which is a GNU extension.  This is
>   the standard stropping regime in GCC, and its rules are similar to
>   the naming conventions widely used in many modern programming
>   languages.  The resulting programs have a very modern feeling.
>
> In GCC we use SUPPER stropping only.  The only instance of UPPER
> stropping are in test cases.  Some of the guidelines and
> considerations in this document may also be useful in programs using
> UPPER stropping.
>
> ## Formatting
>
> The placement of spaces and empty lines in the program text plays an
> important role when it comes to readability.
>
> ### Empty lines
>
> Empty lines are often used in programs to separate logical parts in a
> sequence of statements or expressions.  This avoids the code to look
> like walls of text, which are somewhat difficult to read.  This of
> course also applies to Algol 68, but in a much less degree due to the

course also applies to Algol 68, but in to a much lesser degree due to the


> exceptionally clean syntax of the language.  Therefore we favor a
> compact formatting to a reasonable extent.
>
> Please be frugal with empty lines, especially within enclosed clauses.
>
> It is not necessary nor advisable to have separated "declaration
> parts" in serial clauses, because declarations can appear anywhere.
> However empty lines may still be useful to group related declarations
> together.
>
> It is often better to use an explanatory comment rather than an empty
> line, again especially within enclosed clauses.
>
> ### Spaces before parentheses
>
> Do not put spaces before open-parentheses in routine calls.
>
> But make sure to always put a space between `union' or `struct' and
> the open parenthesis that follows in declarers.
>
> Likewise, please put a space before the open parenthesis when the
> enclosed clause in a cast is a closed clause.
>
> Examples:
>
> ```
> { No space before open-parentheses in calls }
> puts(fixed(count,0) + "'n");
>
> { Space between `union' or `struct' and `(' }
> mode Number = union (int,long int,real,long real)
>
> { Space before '(' in casts }
> ref JSON_Fld (fields) := field;
> ```
>
> ### Spaces after parentheses
>
> When writing routine texts always place a space between the formal
> parameters pack and the mode of the value yielded by the routine.
>
> When writing operator and procedure declarators do not put a space
> between the parameter modes pack and the mode of the yielded value.
>
> Also in declarers, do not put a space after `op' or `proc' and the
> parameter modes pack.
>
> ```
> { Space after formal parameters pack in routine text }
> json_foreach_elem(a, (ref JSON_Val v) void: len +:= 1)
>
> { No space after parameters pack in procedure and operator
>   declarators }
> proc(string)void error;
> ```
>
> ### Spaces within packs
>
> With "pack" we refer to the following source constructs which are
> collections of other constructs enclosed between `(' and `)' symbols:
>
> * The actual parameters in a call.
> * The formal parameters in a routine text.
> * The fields in a struct mode declarator.
> * The modes of the united modes in an union mode declarator.
> * The modes of the parameters in an operator or procedure declarator.
>
> Spaces are optional after commas in packs when both the preceding and
> following symbols are tags.
>
> Put a space after commas in packs when the next construct is not a
> tag, but only if the preceding construct is a tag.
>
> Do not put spaces before commas in packs.
>
> Examples:
>
> ```
> { Spaces are optional around commas surrounded by tags }
> process(socket, resp, fragmented);
> process(socket,resp,fragmented);
> op E = (Symbol a,b) bool: a = b;
> op E = (Symbol a, b) bool: a = b;
>
> { Space after commas separating a non tag and a tag }
> op E = (Symbol s, Word w) bool: s E w;
> mode M = struct (int i, real r);
>
> { No spaces in commas separating non tags }
> proc(int,string,[]real)int callback;
> op(intint)int handler;
> mode Data = union (void,bool,int)
> ```
>
> ### Spaces in row displays
>
> Within row displays spaces are optional after commas, but please never
> put spaces before commas.
>
> ```
> { Spaces are ok after commas in row-displays }
> []int a = (1,2,3);
> []int b = (1, 2, 3);
> []string names = ("jemarch",
>                   "mnabipoor",
>                   "pietr0");
> ```
>
> ### Spaces in formulas
>
> Do not put spaces after monadic operators whose representation is not
> a bold word.
>
> However, if the monadic operator is represented by a bold word, always
> put a space between the operator and the operand, even when the
> operand starts with a parenthesis.
>
> Always put spaces before and after dyadic operators if the formula is
> not parenthesized.  Spaces are optional if the formula is
> parenthesized, provided the operator is not represented by a bold
> word.
>
> Examples:
>
> ```
> { No space after non-bold monadic operators }
> int i = -10;
>
> { Always a space after bold monadic operator }
> int i = ABS (base + offset)
>
> { Spaces in dyadic opeator }
> total := a + b;
> index := cnt +:= 1;
> total := (a + b);
> index := (cnt +:= 1);
> total := (a+b);
> index := (cnt+:=1)
> ```
>
> ### Spaces in bounds
>
> Do not put spaces after the bounds of a declarer.
>
> Also, do not put spaces directly within the bounds of a declarer,
> unless for indentation purposes.  Since bounds can contain any unit,
> the general rules apply within these.
>
> Examples:
>
>
> ```
> { No spaces after bounds in declarers }
> mode List = [10]int,
>      MatrixList = [10][3,3]int,
>      Numbers = []union (int,real);
>
> { No spaces directly within bounds in declarers }
> mode MyString = [1:10@]MyChar,
>      DynamicTable = [read_int(10, 20),
>                      read_int(10, 20)]char;
> ```
>
> ### Spaces in indexers and trimmers
>
> Algol 68 allows using `(' and ')' instead of '[' and ']' in bounds and
> slices to represent the SUB and BUS symbols. This is supported by ga68
> via the `-fbrackets' command-line option in order to ease the porting
> of old code, and it is disabled by default. Please always use square
> brackets for indexing in new code.
>
> While indexing and trimming a multiple, never put a space between the
> indexed tertiary and the SUB symbol.
>
> Do not put spaces direcly within indexers and trimmers, unless for
> indentation purposes.  As an exception to this rule, you can put a
> single space before the "at" operator `@' if desired.
>
> Examples:
>
> ```
> { No space between tertiary and '[' }
> int i = a[i];
> int i = a[10:20]
>
> { No direct spaces within trimmers and indexers, but before @ }
> []int a = b[2:5@10];
> []int c = d[10:20 @1];
> ```
>
> ### Spaces in brief clause forms
>
> It is generally a good idea to have spaces around `|' and `|:' within
> the brief forms of conditional clauses, case clauses and conformity
> clauses.
>
> When the brief forms are very short and the units are number
> denotations, it may be more clear to not use spaces, especially when
> the form is an operand in a formula.
>
> Examples:
>
> ```
> { Space around | and |: in brief forms }
> (v | (void): "empty", (bool b): (b | "true" | "false"))
>
> { No spaces may be more readable sometimes }
> int n = 2 + (c>3|10|20);
> ```
>
> ## Comments
>
> Use "foo" to refer to formal parameters when documenting procedures or
> operators.
>
> Use `whatever' to refer to any other source construct that is not a
> formal parameter.
>
> Examples:
>
> ```
> int error_hash = 0;
>
> { Return a hash code for the string "s", or `error_hash' if the string
>   is too long.  }
>
> proc hash_string (string s)
> ```
>
> ## Syntactic Conventions
>
> ### Closed clauses
>
> Algol 68 allows using `(' an `)' instead of `begin' and `end' to
> delimit closed clauses.  In fact, parenthesized expression in other
> programming languages are realized in Algol 68 with closed clauses, in
> a very orthogonal way.  Both forms are useful and can generally be
> used according to the programmer's taste.  However, this section
> contains a few guidelines and recommendations on this regard.
>
> Use parentheses for closed clauses that span in a single line,

Use parentheses for closed clauses that span a single line,



> regardless of the context.  Having `begin' and `end' symbols in the
> same line looks weird and confusing.
>
> As a general rule, always use parentheses in closed clauses that are
> operands in a formula.  Exceptionally, using `begin' and `end' in
> formula operands may be preferable if the operand contains many
> declarations and units, and only if it spans for more than one line.
> In this case, however, plese consider factoring the code in the

In this case, however, please consider factoring the code in the



> operand into a routine and replace it with a procedure call.
>
> The preferred indentation for a closed clause whose contents span for

The preferred indentation for a closed clause whose contents span



> more than one line, and that uses `begin' and `end' symbols as
> delimiters, is to indent the contents right at the right of the
> `begin' symbol.  The `end' symbol shall then be placed in its own
> line, with the same indentation level than the opening symbol.
>
> If the closed clause contains empty lines, or if the line preceding
> the closed clause is so long that it would "hide" the first line in
> the closed clause, then it is ok to put the first unit or declaration
> in the line after `begin'.  This usually happens when the closed
> clause is the body of a long routine text.
>
> The preferred indentation for a closed clause whose contents span for

The preferred indentation for a closed clause whose contents span


> more than one line, and that uses `(' and `)' symbols as delimiters,
> is to indent the contents right at the right of the `(' symbol.  The
> ')' symbol finishing the closed clause shall not be placed in its own
> line.
>
> ```
> { No `begin' and `end' in the same line }
> int i = 2 + (3+4);
> int i = 2 + (int i = random(); i % 10 );
> bool test = case v in (string): (puts (s); true) out false esac;
>
> { Closed clauses as formula operands }
> int i = 2 + (int cnt := 0;
>              to UPB data[@1] do cnt +:= 1 od;
>              cnt)
> int j = 2 + begin int cnt := 0;
>                   to UPB data[@1] do cnt +:= 1 od;
>                   cnt
>                   end
>
> { Closed clause with no empty lines }
> begin int fd = fopen ("data', file_o_rdonly")
>       puts ("first line: " + fgets (fd, 0));
>       fclose (fd)
> end;
>
> { Closed clause with no empty lines but with preceding
>   line of similar length }
> proc parse_number = int:
> begin
>       int num := 0;
>       while num := num * 10 + ABS ch - ABS "0";
>             isdigi(getachar)
>       do ~ od;
>       ungeachar(ch);
>       num
> end;
>
> { Closed clause with empty lines }
> proc main_proc = int:
> begin
>       { Auxiliary procs }
>       proc aux1 = int: ...;
>       proc aux2 = int: ...;
>
>       { Computation }
>       aux1;
>       aux2;
>
>       { Result }
>       aux1 + aux2
> end
>
> { Indentation of closed clauses using `(' and `)' delimiters }
> proc parse_number = int:
> (int num := 0;
>  while num := num * 10 + ABS ch - ABS "0";
>        isdigi(getachar)
>  do ~ od;
>  ungeachar(ch);
>  num)
> ```
>
> ### Conditional clauses
>
> If a conditional clause is still clear and not of excessive length
> when written on a single line, just do it.
>
> Start the enquiry clause in the if-part of a conditional clause right
> after the `if' symbol, not in the next line.
>
> The serial clauses in the then- and if-parts of the conditional clause
> shall be indented five positions right, which is the length of both
> the `then' and `else' symbols plus one.
>
> The first declaration or unit in the tehn- and if-parts shall be

The first declaration or unit in the then- and if-parts shall be



> placed in the same line than the `then' and `else' symbols,
> respectively.
>
> Place the `fi' closing symbol in its own line, with the same
> indentation level than the matching `if'.  The exception to this rule
> is when the conditional clause has no else-part and the then-part
> spans for a single line that is not too long.  In that case, place the
> `fi' in the same line than `then'.
>
> Examples:
>
> ```
> { Very small conditional clause in a single line }
> if idx < 0 then fatal("invalid idx") fi
>
> { Short conditional-clause with `fi' in the same line
>   than `then' }
> if argc /= 3
> then puts("expected two arguments'n") fi
>
> { A conditional-clause that spans for several lines }

{ A conditional-clause that spans several lines }



> if a > 10
> then puts("truncating");
>      a := 10
> fi
> ```
>
> ### Loop clauses
>
> If a loop clause is small enough to fit in a single line without
> occupying most of it, just do it.
>
> If a loop clause spans to two lines, and the second line is not too

If a loop clause spans two lines, and the second line is not too



> long, you can put `od' in the same line than `do'.
>
> If a loop clause spans to several lines, please put the `do' symbol in
> its own line, indented to the same level than the clause's frobyts.
>
> Examples:
>
> ```
> { Very short loop-clause in a single line.  }
> for a to argc do puts ("arg: " + argv[a]) od;
>
> { Short loop-clause with `od' in the same line than `do' }
> for i from LWB a to UPB a
> do total +:= a[i] od
>
> { A loop-clause that spans for several lines }

{ A loop-clause that spans several lines }



> while NOT exit
> do string cmd = get_command;
>    process_command(cmd)
> od
> ```
>
> ### Case and conformity clauses
>
> Do not write a case or conformity clause in a single line, unless
> you are using the brief form.  Unlike conditional and loop clauses,
> these are difficult to read.
>
> Please put the `in', `out' and `ease' symbols in their own lines, with
> the same indentation level than the matching `case'.
>
> Start the choices right after the `in' symbol, in the same line.  All
> the choices may fit in a single line.  If they don't, please put each
> choice in its own line.
>
> ```
> { Short case clause }
> case i
> in 100, 200, 300 out 0 esac;
>
> { Long case clause }
> case i
> in 100,
>    200,
>    300
> ouse i % 100
> in 100,
>    200,
>    300
> esac;
>
> { Long conformity clause }
> case v
> in (void): "empty",
>    (bool b): (b | "true" | "false"),
>    (string s): s
> esac
> ```
>
> ### Procedure and operator declarations
>
> In procedure and operator declarations, if the body of a routine text
> starts with 'begin', put it at the same indentation than the `pub',
> `proc' or `op'.  Otherwise, indent it three spaces to the right
> relative to the `pub' `proc' or `op'.
>
> Examples:
>
> ```
> { Body of routine is a `begin'..`end' closed clause }
> proc checked_div = (int a,b) int:
> begin
>       if b = 0 then fatal ("div by zero") fi;
>       a % b
> end;
>
> { Body of routine does not start with `begin' }
> proc checked_div = (int a,b) int:
>    (b = 0 | fatal ("div by zero"); skip | a % b);
>
> { Body of routine is not a closed clause }
> proc checked_div = (int a,b) int:
>    if b = 0
>    then fatal ("div by zero"); skip
>    else a % b
>    fi;
> ```
>
> ### Contracted declarations
>
> Please don' be shy to use contracted forms of declarations.  They can

Please don't be shy to use contracted forms of declarations.  They can




> make the program much more readable and they make it easier to add new
> declarations, because they prevent writing the same text again and
> again.
>
> However, care should be taken when declarin operators and procedures.

However, care should be taken when declaring operators and procedures.


> In these cases, contracted declarations should only be used when
> declaring very short, one or two lines long routines.  The last
> routine in the list of joined declarations can be a bit longer.
>
> Examples:
>
> ```
> { Contracted declarations lead to compact and very
>   readable code }
> int disconnected = 0, connected = 0, unknown = 2;
> pub ref JSON_Val json_no_val = nil,
>     ref JSON_Elm json_no_elm = nil;
>     ref JSON_Fld json_no_fld = nil;
>
> { Use contracted declarations for short routines }
> op + = (States ss, State s) States: MoreStates (heap States := ss, s),
>    + = (Transitions ts, Transition t) Transitions:
>          MoreTransitions (heap Transitions := ts, t)
> ```
>
> ### Brief clause forms
>
> The obvious context where to use the brief forms of conditional, case
> and conformity clauses is when these clauses appear as operands in
> formulas.  They match well with parenthesized closed clauses.
>
> It is also ok to use brief forms of clauses out of formulas,
> especially inside case and conformiy clauses.  But please be careful,
> as brief forms may be confused sometimes.
>
> Examples:
>
> ```
> { Brief forms in formulas }
> int res = (a=0 | fatal("div by zero"); skip | den/a);
>
> { Brief forms out of formulas }
> for i to ELEMS str
> do char newline = REPR 10, tab = REPR 9, c = str[i];
>    (c = "\" | res +:= "\\"
>     |: c = newline | res +:= "\n"
>     |: c = tab | res +:= "\t"
>     |  res +:= c)
> od
> ```
>
> ## Naming
>
> Unlike most other programming languages, which are not stropped, in
> Algol 68 it is possible to have tags with the same name than reserved

Algol 68 it is possible to have tags with the same name as reserved



> words, by appending an underscore character to the tag. For example, a
> tag `if' can be written as `if_'.  It is important to note that the
> trailing underscore is not part of the tag: it is just a stropping
> artifact. This is always better than contriving artificious synonyms
> that are often confusing or too long.  A copying routine has arguments
> "from" and "to"? Call them `from_' and `to_'. A struct mode has fields
> "in" and "out"? Call them `in_' and `out_'.
>
> Please use fully uper-case bold words for operator indicants.  This

Please use fully upper-case bold words for operator indicants.  This



> makes it easier for text editors to highlight them in a different
> style than mode indicants, and look more symmetrical in case of dyadic
> operators.  For example, use `ABS' and not `Abs'.
>
> ## Programing style
>
> This section contains some recommndation on the usage of the
> facilities of the language.
>
> ### Writing routines
>
> Use routines liberally!  Routines are cheap, very easy to write thanks
> to the excellent Algol 68 syntax for routine texts, and first-class
> citizens in the language.  They also have access to the lexical
> environment.  So if you find yourself wanting to write a macro in
> order to repeat some little calculation, just write a small procedure
> or operator instead.
>
> Choose identifiers that are expressive of meaning in order to clarify
> both the intent of the procedure or operator and the code written that
> uses it.
>
> Consider using overloaded operators in preference to procedures with
> united mode parameters to encourage users of the operator to create
> new versions of the operator for different parameter types, rather
> than leaving the users trying to figure out how to hack the united
> mode definition.
>
> The high level of orthogonaliy of Algol 68 combined with the
> structural type equivalence and the nice compact syntax of declarers
> makes mode names way less relevant than in many other programming
> languages.  In particular if a routine takes a parameter that is an
> united mode, and that particular united mode is either not used
> anywhere else or very short, just write the declarer, you don't have
> to name it first.
>
> Please make good use of the lexical block structure of the programming
> language: is is there to be used.  In little local auxiliary routines,
> do not add arguments just to pass a value thas is in the environment,
> unless the declaration of the later is very far away from the routine
> text: make the routine access the value itself.
>
> ### Nihils
>
> Never use `nil' directly in identity relations; it is very error
> prone.  It is better to define "nihils" for all reference modes that
> are likely to appear in one.
>
> Examples:
>
> ```
> mode Node = ...;
> ref Node no_node = nil;
> while n :/=: no_node do ... od


More information about the Algol68 mailing list