[DRAFT] An UNSAFE clause for Algol 68

Jose E. Marchesi jemarch@gnu.org
Sat Apr 19 15:32:54 GMT 2025


 An UNSAFE clause for Algol 68
*****************************

                        gnu68-2025-001 (draft)

Copyright © 2025 Jose E. Marchesi.

     You can redistribute and/or modify this document under the terms of
     the GNU General Public License as published by the Free Software
     Foundation, either version 3 of the License, or (at your option)
     any later version.

The following specification has been released under the auspices of the
GNU Algol 68 Working Group, and has been scrutinized to ensure that

  a. it is strictly upwards-compatible with Algol 68,
  b. it is consistent with the philosophy and orthogonal framework of
     the language, and
  c. it fills a clearly discernible gap in the expressive power of that
     language.

The source of this document can be found at
<https://git.sr.ht/~jemarch/gnu68>.

The informal description of this proposal introduces the proposed new
language features, providing a rationale and usage examples.

The formal definition of this proposal uses the existing formalism and
conventions of the Revised Report, and it is expressed as modifications
to the Report.

Finally, the implementation notes of this proposal describes a way in
which the features added by this specification can be implemented.  No
implementer should feel committed to do things as described there; the
same language facilities may well be implementable in other ways, more
suitable to specific implementations.

1 Informal Description
**********************

Safety in Algol 68
==================

Safety, understood as the level of resilience of a program against
malfunctioning, or even crashing, with potentially harmful effects, is
an important matter.

The Algol 68 programming language is designed with program safety in
mind, as can be quoted from the section 0.1.3 of the Revised Report:

     Algol 68 has been designed in such a way that most syntactical and
     many other errors can be detected easily before they lead to
     calamitous results.  Furthermore, the opportunities for making such
     errors are greatly restricted.

Despite of the good intentions, there are several actions in Algol 68
that will lead to what the Report describes as an “undefined” state.
These include indexing a multiple using indexes that are out of bounds,
dereferencing ‘NIL’, or calling a procedure whose scope is newer than
the current scope.  Many of these events may lead to unsafe situations
unless handled somehow.

The main way to handle unsafe situations is to avoid the situations to
even arise.  This requires detecting them, and here is where the design
of the programming language plays a big role.

Static and Dynamic Safety Checks
================================

Designing a programming language with safety in mind means that the
language is designed in such a way that allows implementations to check
for actual and potentially harmful situations.  A typed programming
language, for instance, makes it possible to detect situations where two
values of disparage nature get combined.

This sort of checking can be done statically or dynamically.  Static
checking is performed at compile-time by the compiler, translator or
interpreter.  Dynamic checking is performed at run-time by code
generated by the compiler along with the program's code.  It is
generally agreed that the more safety checks can be performed
statically, the better.  This is due to several reasons, most of them
pretty obvious.

In Algol 68 the set of all actions that lead to an undefined state can
only be generally handled via dynamic checks.  It is in general not
possible, for example, to determine statically whether some given
reference is not ‘NIL’.  In order to cover all possibilities a run-time
check would need to be generated.  Algol 68 is designed in a way,
however, that the vast majority of cases can indeed be detected
statically.

Compiler Safety Modes
=====================

As discussed above, every Algol 68 implementation is required to
implement a “dynamic safety mode” in order to guarantee that the
compiled programs will run safely.  Run-time checks shall be generated
in order to:

   • Perform bounds checking when assigning multiples and when indexing
     and trimming.
   • Perform scope checking before dereferencing a name and before
     calling a procedure or operator.
   • Perform ‘NIL’ checking before dereferencing.

The implementation may provide the possibility of disabling all or some
of the checks above, using command-line options or other configuration
means.  This is usually done with the goal of emitting faster programs,
which will have to be assumed as properly tested and therefore
guaranteed to execute safely when confronted with input comparable to
the one exercised during testing.

The dynamic safety mode is almost always accompanied with static checks
performed by the compiler that may result in diagnostics at
compile-time.  These diagnostics may be errors or warnings, and the
implementation may provide the means to turn particular warning into
errors.

Additionally, an implementation may want to implement a “static safety
mode”, in which the set of Algol 68 programs that can be compiled is
reduced to the set of programs for which it can be stated statically
they will execute safely.

The feasibility of a static safety mode mainly depends on the particular
programming language, whose design will determine whether the reduced
set of "safe" programs is practical and useful, and to a lesser degree
on the sophistication of the implementation and on the application
domain of the language.  A C compiler, for example, would have a very
hard time implementing a static safety mode in a way the resulting
restricted language would be still useful.

The ‘UNSAFE’ clause
===================

Regardless of the safety mode of operation in use, static safety checks
determine which source constructs are known to be safe, which ones are
known to be unsafe, and which ones are not known to be safe.

Compiling source constructs that are known to be safe does not result in
any diagnostic message and the resulting compiled code may not perform
run-time safety check.

Compiling source constructs that are known to be unsafe must result in
an error message and the compilation gets interrupted.

Finally, compiling source constructs which are not known to be safe may
result in a warning message and the resulting compiled code must perform
run-time safety checks.  If the compiler is working in a static safety
mode, the warning message turns into an error and the compilation gets
interrupted.

This extension provides a new source construct, the “unsafe clause”,
which contains a controlled enclosed clause.  In the following example,
the controlled clause is a closed clause:

     UNSAFE (dest := src)

The effect of ‘UNSAFE’ is to signal to the compiler that the programmer
acknowledges the possible presence of not known to be safe constructs in
the controlled clause, and a directive to assume the controlled clause
is actually known to be safe.

2 Formal Description
********************

An “unsafe clause” is a new kind of enclosed clause.

     1.2.2
       A) ENCLOSED :: ... ; unsafe.

The unsafe clause contains a “controlled clause”.  The value yielded by
the unsafe clause is the value yielded by the controlled clause.

     3.7 Unsafe clauses

     3.7.1 Syntax

     a) SOID NEST unsafe clause :
          unsafe{94f} token, SOID NEST ENCLOSED clause{a,31a,33a,c,d,e,34a,35a,-}.

     { Examples:
        a) UNSAFE (ptr := dst)  }

     3.7.2 Semantics

     a) A SOID-NEST-unsafe-clause N, in an environ E, is elaborated as
        follows:
        . The yield of N in E is the yield of the ENCLOSED-clause of N
          in E.

A new symbol has been invented, with a proposed representation in the
reference language.

     9.4.1.f
       unsafe symbol{37a}                   UNSAFE

3 Implementation Notes
**********************

Since the proposed extension doesn't have any impact in the semantics of
the language, adding it to an existing implementation should be pretty
straightforward.  We thus limit these notes to just hint what would be
needed to do in a typical implementation.

First the scanner shall be expanded so it recognizes the token
representing arg.  In an implementation following the reference language
this must be ‘UNSAFE’ in bold face letters.

Then the internal representation of the parse tree shall be expanded to
feature an extra kind of node representing the unsafe clause, which is a
new kind of enclosed clause and therefore a primary.

The mode checking pass shall simply set the mode of the unsafe clause to
the mode of its controlled clause.  Similarly, the pass in charge of
inserting coercions shall move the coercion into the controlled clause.

A pass that checks for static scope violations should either not analyze
the controlled clause of an unsafe clause, or refrain from any
diagnostic action if it finds a potential or even certain scope
violation within the controlled clause.

Finally, the code generator shall be modified so the code generated for
the unsafe clause is simply the code generated for the controlled
enclosed clause, maybe with variations in terms of what run-time checks
get generated.


More information about the Algol68 mailing list