Greetings and introductions
chris hermansen
clhermansen@gmail.com
Thu Jun 19 18:02:30 GMT 2025
Good morning Jose and everyone,
On Wed, Jun 18, 2025 at 4:10 PM Jose E. Marchesi <jemarch@gnu.org> wrote:
[snip]
>> > After using Algol 68C in my undergraduate years in the latter half of
>> > the 1970s, I haven't done much more with it than wish that I had a
>> > decent Algol 68 compiler since then, until I stumbled on Marcel's
>> > wonderful Algol68g a few years ago. Since that time, I have written
>> > many insignificant programs to recover my knowledge and at one point
>> > built a first version of a hash table capability based on
>> > split-ordered lists(1) in Algol68g, which at least works, but needs
>> > some cleaning up.
>>
>> It would be great to get these hash tables working with GCC. I could
>> certainly make good use of them in some of my projects.
[snip]
> Let me know if you want mine and/or the C (C++) version.
The Algol 68 one :)
Sent earlier today to your address. If you wait for a bit I might have a
working and somewhat cleaner version running under GNU Algol 68.
>>
>> At the moment, as you probably know, we don't have support (yet) for
>> separated compilation, but we manage by including the files. See for
>> example how the sources are organized in
>> https://git.sr.ht/~jemarch/godcc.
>>
>
> That's how I handled using the hash tables in Algol 68 Genie (as
includes).
>
>>
>> We also plan to implement modals, but until we do so, I suppose using
>> your hash table implementation will require to manually define some
>> modes before include the source file...
My current code accepts INT and STRING keys and INT, DOUBLE and STRING
values.
No reason why we couldn't leave the whole definition of KEY and VAL modes
to the user, to be defined separately before use of the hash table.
In my code, there are conformity-clauses to handle key comparison, mode
conversion, etc. So not as simple as just defining a new united-mode.
> > See my comment above about maps of maps, which may be an acceptable
> > workaround for some of us.
> >
> > But yes I think the only way to make hash tables generally work with
Algol
> > 68 modes is to have access to united modes similar to SIMPLIN at least,
and
> > with some way to handle STRUCT values.
> The ALGOL-68RS compiler, and its retargetted algol68toc, implements an
> extension that allows programmer to do straightening explicitly, the
> form of a new mode STRAIGHT and a new coercion "straightening" available
> in strong contexts.
> The extension was provided mainly to allow implementing unformatted
> transput in Algol 68, and I am considering to implement it for that
> purpose, and also because it provides a great level of introspection for
> user-defined modes... maybe to the level of facilitating hashing them?
This is an interesting concept. The excessive magic (in a very non-magical
language) that causes straightening to "just work" when dealing with
transput has always bothered me; and of course, why only transput?
>
> From the rscompiler manual:
> D.3 Straightening
> A `straightening' facility is provided to enable Algol 68 programmers
> to write transput procedures with arbitrarily structured
> parameters. Straightening is the reduction of any type of data
> structure to a simple sequence - which we shall describe as a
> straight. The basic step is the coercion of a simple row or structure
> to a straight; applied recursively, the method can be used to
> straighten data structures of arbitrary complexity.
> The mode STRAIGHT U, where U is any Algol 68 mode (but most commonly a
> union), describes a set of objects of mode U. In this respect it is
> similar to [] U, but in other respects it is quite different and must
> be treated as a new type of mode. An actual straight is brought into
> existence by strong coercion of a row, vector, structure, i-struct or
> union. Such modes are strongly coercible to STRAIGHT U if their
> "members' can be coerced to U by uniting, straightening or any of the
> coercions i-struct to vector to array (A4.1). The coercions excluded
> are dereferencing, deproceduring, widening and rowing.
It's not immediately obvious to me why these four coercions are excluded.
In the Revised Report, I don't believe these coercions are excluded from
the straightening that happens in transput (but I could certainly be wrong).
Not allowing dereferencing in particular seems problematic to me, since it
seems it would be quite likely to want to pass REF INT for example.
>
> Example 1
> STRAIGHT UNION (INT, CHAR) s1 = "ABCD"
> As CHAR is coercible to UNION(INT, CHAR), the i-struct "ABCD" can be
> coerced to the STRAIGHT. If s1 were the formal parameter of an output
> procedure, acceptable actuals would be a row of characters, row of
> integers, structure with integer and character fields or a union of
> integer and character. However, a single INT or a single CHAR would
> not be accepted.
I see the "single INT or single CHAR" restriction corresponds to excluding
rowing as per the D.3 description. As I said above, I don't get why.
> Example 2
> STRUCT (INT i, REAL r) p;
> STRAIGHT UNION (REF REAL, REF INT, REF CHAR) s2 = p
> The members of p have modes REF INT and REF REAL, both of which are
> coercible to the given union, so p will be coercible to the mode of
> s2. Clearly, s2 might be the formal parameter of an input procedure
> and p its actual parameter. The actual could not be a simple real,
> integer or character variable.
> Example 3
> [3] INT v := (1, 2, 3);
> STRAIGHT INT s = v;
> In this example, the members of the variable v have mode REF INT, but
> s is a straight of plain integers. As it stands, v cannot be
> straightened to s because dereferencing of members is not allowed. But
> as v can be dereferenced before straightening, the example is
> correct. Consideredas a formal parameter for an output procedure, s
> would handle any row or structure of integers, but not a single
> integer by itself.
Again because of not allowing rowing.
>
> As a straight cannot represent an unstructured value, most
> applications will demand that it be combined with basic modes in a
> union, eg
> UNION (INT, REAL, ... , STRAIGHT UNION (INT, REAL, ... ))
> This mode will handle an object of data which possesses structure at
> no level (eg an INT) or one level (eg [] REAL, STRUCT 17 INT) but not
> more. When an object is being united to the above mode, then ---
> regardless of the order in which the constituent modes have been
> written --- the fit will be sought from the non-STRAIGHT modes first,
> so as to avoid any possible ambiguities of coercion.
> To handle one object structured at any number of levels, a recursive
> mode is needed.
> MODE PRINTMODE = UNION (INT, REAL, ... , STRAIGHT PRINTMODE)
> The definition of STRAIGHT is such as permits this recursion. PRINTMODE
> will handle an integer, real, etc, or any row or structure built up
> from all these to any depth. For a corresponding input parameter mode,
> the basic modes would each be preceded by a REF.
> The parameter of the standard print procedure has mode VECTOR []
> PRINTMODE rather than RINTMODE. This allows the use of a collateral as
> the actual parameter.
> A straight cannot be handled with the full generality applicable to
> other Algol 68 modes.
Is this a conceptual limitation or a decision taken to facilitate the
compiler construction? I think it's important to understand that, because
it seems to strike at the principle of orthogonality otherwise.
>
> The manipulations are confined to subscripting and interrogation by the
> operator UPB. Let m stand for any mode, and let s have mode STRAIGHT
> M. Then UPB s gives the number of objects in the straight, and s[i]
> picks out the ith object (i >= 1). There is no such thing as a STRAIGHT
> generator or variable because objects of mode REF STRAIGHT do not
> exist.
Would be good to understand why REF STRAIGHT cannot exist.
In sum I think this has potential, but since STRAIGHT doesn't behave like
other Algol 68 modes, I think its formalism needs to be fully described.
> >
> >>
> >> > As a great fan of Java, I would love to see Algol 68 evolve a little
bit
> >> in
> >> > the direction of being object-oriented; thinking specifically of
STRUCTs
> >> > that could refer to "self", simple / single inheritance, MODE
templates,
> >> > interfaces. From my perspective, that would require some very
careful
> >> > thinking and design work and being willing to draw a boundary much
closer
> >> > to Algol 68 classic and much further away from C++.
> >>
> >> I am personally not the biggest fan of object orientation, but having
> >> support for it in an "Algol 68 way" would be useful to have, and quite
> >> interesting to design.
> >>
> >
> > I think that point is key. From the point of view that the two level
> > grammar and extreme orthogonality buy so much when applied to what
amounts
> > to what is otherwise a pretty small language definition, how might
modest
> > but useful object orientation fit into that design?
> >
> > I've never used Simula but there might be some clues there.
> Yes that's the challenge...
If I'm not wrong, an Algol 68 mode declaration is similar to a Java
interface definition - behaviour is not defined until the interface is
implemented or the mode is used in a declaration or initialization (or I
guess in an update).
So my claim would be that this is OK, but I'd also like to be able to:
attach the behaviour implementation to the mode declaration, or possibly
have some form intermediate between the mode declaration and the
declaration of a name where the behaviour can be attached;
be able to inherit the behaviour via a new mode declaration or the
hypothetical intermediate form
For example, if I wanted to define a mode like INTYPE but with a "hash"
proc and a "toString" proc, and I wanted to then go on to define more modes
based on that...
I haven't thought this through clearly; these are just ideas spinning
around in my head. But I'm not advocating just bolting something like this
on without a good long and careful think first.
> >
> >>
> >> > I might be in the minority but I would see this extension being much
> >> > more useful than implementing transput in all its "glory".
> >>
> >> I agree with that. There are a lot of good ideas in the standard
> >> transput that I think would be useful to recover, but after some
(much?)
> >> modernization.
> >>
> >
> > Or... implement printf and scanf? Just sayin'... Seems like those
would
> > be pretty straightforward in Algol 68 since one would only have to deal
> > with base types.
> I was thinking more about unformatted transput, straightening, the
> handling of encoding, event-driven handling of transput errors and
> conditions (this can be "merged" with the exceptions mechanism we adopt)
> etc.
> My feeling is that formats are simply too complicated, but I have never
> used them myself for anything more complex than toys, so the feeling is
> in no way backed by any actual experience...
Completely in agreement with you. Not only are Algol 68 formats too
complicated, but they don't look like anything that's come along since (at
least, that I know of); and for all their complexity, they are built
without knowledge of anything other than fixed-width characters. Whereas
the utility of scanf() and printf() has been well proven, as have some of
the more complex formatting schemes such as those in Java.
[snip]
> An alternative way of handling parallelism in Algol 68 was actually
> implemented as an extension by the algol68-s compiler: "eventual
> values", which involves two coercions "evening" and "deventing".
>
> This is an excerpt from the ALGOL-S user manual:
>
> Parallel-clauses have several disadvantages. First, the fork and join
> points must be nested not only with respect to other parallel-clauses,
> but also with respect to the routine and range structure of the
> program. This can be undesirable if an activity to be started in
> parallel does not interact with the further elaboration of other
> activities. A particular irritation is that it is not possible to
> start an activity within a routine and have it complete after the
> routine. Second, since the piece of program which may be initiated in
> parallel is a void unit, a parallel activity may not return a value
> except through the use of global variables. The possibility for
> programmer error is increased because other parallel activities may
> access these variables. Alternatively, the programmer may decide to
> use parallelism only for subprograms which return no values. This has
> the unfortunate consequence of reducing the amount of parallel
> processing. Finally, synchronization within the parallel-clause scheme
> is accomplished by scattering up and down operations throughout the
> program. This decentralization of control can be as difficult for
> programmers to deal with as the unrestricted use of the goto.
>
> The idea behind eventual values may be seen by considering the
> following piece of program:
>
>
> real x, y;
> x := sin (3.2);
> unit1 .... ; unitn;
> y := x + 1.0
>
> When more than one processor is available it would make sense to allow
> sin (3.2) to be computed in parallel with the elaboration of the first
> assignation and the units Unit1, ..., UnitN. In this case the value
> assigned to x can not be the desired real value since it is not
> necessarily available at the time of the assignation. The value
> assigned is one which will eventually (when the call completes) be a
> real value. We call this kind of value an eventual real value. When
> the second assignation is reached it is necessary to produce a real
> value from the eventual real value; that is, the program must wait for
> the call of sin to complete. These ideas are incorporated into the
> language by formally defining an eventual value to be a new object,
> and by introducing two new coercion actions, deeventing and eventing.
>
> The mode of an eventual value is event amode, where amode is any
> mode. An event amode value is composed of a status, which is either
> complete or incomplete, and an amode value.
>
> An event amode value may be "deevented" to an amode value much as a
> proc amode value may be deprocedured to an amode value. In fact,
> deeventing may occur in the same syntactic positions as
> deproceduring. Deeventing is used to wait for the amode value to be
> computed. Specifically, if an event amode value has a status of
> complete, then its amode value is yielded by deeventing. If the status
> is incomplete, deeventing causes the current activity to be halted
> until the status changes to complete. Then the activity is resumed and
> the amode value is yielded.
>
> An amode value may be "evented" to an event amode value. This coercion
> may occur in firm and strong syntactic positions. if the construct to
> be evented is a call or formula which returns an amode value then the
> routine is invoked as a parallel activity and the yield of eventing is
> an event amode value with incomplete status. For other constructs the
> yield is an event amode value which is complete and has the amode
> value associated with it.
>
> The previous example may be written as follows:
>
> event real x; real y;
> x := sin (3.2);
> unit1 ; ... ; unitn;
> y := x + 1.0
>
>
> The mode of x is ref event real. The call of sin occurs in a strong
> event real context. The mode of sin is proc (real) real, so it is
> evented by initiating a parallel activity and yielding an incomplete
> event real which is assigned to x. When x is used as a real operand it
> is dereferenced and deevented. The deeventing waits, if necessary, for
> the parallel activity to complete and return the real value which is
> needed.
>
> Another useful application of eventual values is to start the parallel
> elaboration of an independent action. For example,
>
> mode task = event void;
> ...
> task (print ((a, b, c)));
> ...
>
> The cast puts the call to print in a strong event void context, so the
> call is made in parallel. The program never waits for the completion
> because no deeventing ever occurs. Remember, the cast is a comorf and
> is voided directly. If it were necessary to wait for the completion,
> the following could be written:
>
>
> task x;
> x := print ((a, b, c));
>
> x; { wait }
>
>
> The applied identifier, x, is not voided directly, so deeventing occurs
and
> causes a wait.
>
> By now the reader can understand and appreciate the beauty of this final
> example:
>
> op + = (event [,] real a,b) [,] real: ... { usual matrix add };
> op * = (event [,] real a,b) [,] real: ... { usual matrix multiply };
> [1:10,1:10] real a, b, c, d, x;
>
> x := a*b + c*d
This sounds pretty interesting to me, but again I'm no expert.
>>>
>>>>
>>>> So the world domination plan goes like this:
>>>>
>>>> 1. Modern Algol 68 compiler in the form of a GCC front-end,
functionally
>>>> complete. This is basically done. Then optimize the front-end,
>>>> which is work in progress.
>>>>
>>>> 2. Add extensions to the language, carefully describing them both
>>>> formally and informally, with two main goals:
>>>>
>>>> 2.1 To fill gaps in functionality. Examples of these kind of
>>>> extensions are modules, exceptions, modals, OOP, etc.
>>>>
>>>> 2.2 To modernize the language. Examples of these kind of extensions
>>>> are the modern SUPPER stropping, bold taggles, nestable
comments,
>>>> etc.
>>>>
>>>> 3. Use the language! I am already writing some of my new programs in
>>>> Algol 68 ;)
>>>>
>>>
>>> Sounds like a winning plan! The only thing I would add is the need to
>>> spread the good word, and I'm certainly willing to help with that (as
well
>>> as any other contributions I could make to your items 1, 2 & 3).
>>
>> Thank you!
>>
>> I am preparing some materials for a few talks and articles about the
>> project, as time allows. I also plan to speak about the GCC front-end
>> implementation in this year's GNU Tools Cauldron conference in
>> September.
Feeling inspired here, but I'm going to start building a series of small
examples that I can publish as a series of articles on https://www.both.org
as an alternative introduction to Algol 68.
[snip - texinfo did the trick]
>> 3. I ran into what I think might be a bug in puts() where "\n" is not
>> interpreted as a newline.
>
> The standard hardware representation mandates that string breaks shall
> begin with apostrophe. This is an excerpt from the ga68 manual, section
> "String breaks":
>
> 4.6 String breaks
> =================
>
> The intrinsic value of each worthy character that appears inside a
> string denotation is itself. The string ‘"/abc"’, for example,
> contains a slash character followed by the three letters ‘a’, ‘b’ and
> ‘c’.
>
> Sometimes, however, it becomes necessary to represent some non-worthy
> character in a string denotation. In these cases, an escape
> convention has to be used to represent these extra string-items. It
> is up to the implementation to decide this convention, and the only
> requirement imposed by the Standard Hardware Representation on this
> regard is that the character used to introduce escapes, the “escape
> character”, shall be the apostrophe. This section documents the
> escape conventions implemented by the GNU compiler.
>
> Two characters have special meaning inside string denotations: double
> quote (‘"’) and apostrophe (‘'’). The first finishes the string
> denotation, and the second starts a “string break”, which is the Algol
> 68 term for what is known as an "escape sequence" in other programming
> languages. Two consecutive double-quote characters specify a single
> double-quote character.
>
> The following string breaks are recognized by this compiler:
>
> ''
> Apostrophe character '.
> ‘n
> Newline character.
> 'f
> Form feed character.
> 'r
> Carriage return (no line feed).
> ‘t
> Tab.
> '(list of character codes separated by commas)
> The indicated characters, where each code has the form ‘uhhhh’ or
> ‘Uhhhhhhhh’, where ‘hhhh’ and ‘hhhhhhhh’ are integers expressing
> the character code in hexadecimal. The list must contain at least
> one entry.
>
> A string break can appear as the single string-item in a character
> denotation, subject to the following restrictions:
>
> • List of characters string breaks '(...) that contain more than one
> character code are not allowed in character denotations. If the
> specified code point is not a valid Unicode character then the
> value of the denotation is ‘invalid char’.
>
> You may want to take a look at the ga68 manual. It documents the
> implementation-specific preludes, the supported stropping regimes, etc.
> It is built when you build GCC with the algol 68 front-end.
>
> The manual is still of course work in progress, but already useful,
> hopefully.
Super useful, and with the "texinfo" help I was able to build the manual!
>>> There is some documentation on how to build ga68 at
>>> https://gcc.gnu.org/gcc/Algol68FrontEnd.
I believe that link should be
https://gcc.gnu.org/wiki/Algol68FrontEnd
Which is where I got the idea to try "\n" instead of "'n".
[snip]
>> Very excited! If it doesn't create too much noise for the list, I'll
post
>> the occasional comment / code snippet here.
> Sure, that would be awesome :)
> Salud!
Again, many thanks; I hope the comments above are useful.
--
Chris Hermansen · clhermansen "at" gmail "dot" com
C'est ma façon de parler.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://gcc.gnu.org/pipermail/algol68/attachments/20250619/c5c0a67e/attachment-0001.htm>
More information about the Algol68
mailing list