[RFC 1/3] a68: initial Algol 68 standard prelude in libga68

Jose E. Marchesi jemarch@gnu.org
Wed Dec 10 21:03:13 GMT 2025


Hi Chris.

> Jose and list,
>
> On Wed, Dec 10, 2025 at 8:42 AM Jose E. Marchesi <jemarch@gnu.org> wrote:
>
>>
>> Most of the standard prelude is implemented in a combination of code
>> lowered by the front-end (standard operators, contants, etc) and
>> functions provided by the libga68 run-time library, to which the
>> former libcalls.  Until now, all the support routines in libga68 were
>> written in C.  However, many of the transput facilities are better
>> implemented in Algol 68.
>>
>> The Revised Report includes an implementation (code listing) of many
>> of the standard routines.  This implementation, however, makes use of
>> an "extended" program notation in order to denote certain notions to
>> avoid repetitive code.  Therefore this commit includes sppp, a
>> build-time pre-processor written in awk that is only intended to be
>> used internally by the libga68 run-time library.  This preprocessor
>> allows us to write code like:
>>
>
> I saw your earlier message about sppp but have been up to my eyeballs in
> day-to-day stuff, so I'll comment in this email briefly before I return to
> the other one.
>
> This is a nice solution for anyone needing to write something dealing with
> SIZETY and I see it follows Dick Grune's suggestion in §4 of "TOWARDS THE
> DESIGN OF A SUPER-LANGUAGE OF ALGOL 68 FOR THE STANDARD PRELUDE", namely
> that the L problem be mostly resolved by a macro processor.  I'm not
> pretending to have read what you've done with sppp and compared it with the
> (dense) detail in Grune's paper, but on the surface, it's nice to be able
> to follow at least somewhat in his footsteps.

Yes, definitely.  The definition of the scratched-< and scratched-> in
the Report is almost described implicitly in terms of macro-processing.
It is only natural to implement it like this.

>>     proc subwhole = (Number v, int width) string:
>>        case v in
>>           {iter L {short short} {short} {} {long}    {long long}}
>>           {iter S {LENG LENG}   {LENG}  {} {SHORTEN} {SHORTEN SHORTEN}}
>>           ({L} int x):
>>              begin string s, {L} int n := x;
>>                    while dig_char ({S} (n MOD {L} 10)) +=: s;
>>                          n %:= {L} 10; n /= {L} 0
>>                    do ~ od;
>>                    (UPB s > width | width * errorchar | s)
>>              end
>>           {reti {,}}
>>        esac;
>>
>
> I like the way above sppp links the L values and S values.  I struggled
> with my reading of this in the Revised Report, but you clearly have it
> right.

I can tell you I didn't get it right at the fist attempt, nor the
second :)

> One remaining uncertainty for me is "what if I declare some value as long
> long long long long int"?  I know that ga68 only differentiates between
> int, long int and long long int, but does it not also allow me to declare
> longer ints?

It does, you can declare longer (and shorter) ints and reals.

Of course WIDEN and SHORTEN don't follow (there are not an infinite
number of these operators defined, which would have been proper IMO) so
you would get a compile-time error.

>> Resulting in cases for short short int, short int, int, long int and
>> long long int being macro-expanded in the routine's conformance
>> clause.
>>
>> This commit adds the necessary infrastructure for writing Algol 68
>> code in the libga68 library, including the ability of having modules
>> exported by libga68.  An implementation of some of the transput
>> routines is also provided in standard.a68: whole, fixed, float,
>> string_to_L_real, char_in_string, L_int_width, L_real_width and
>> L_exp_with.
>>
>
> Presumably, since these transput routines rely on other standard library
> routines (for example, op ABS), sppp must also be used to define those proc
> and operator definitions?  For example,
>
> op ABS = (L int a) L int: (a < L 0 | -a | a)
>
> must be rewritten using sppp.  I guess this could be
>
> {iter L {short short} {short} {} {long}    {long long}}
> op ABS = (L int a) L int: (a < L 0 | -a | a)
> {reti {;}}

That's the idea in general.

At the moment the ABS operators are implemented directly in the
front-end, i.e. the compiler compiles to an inline expression for them.

It would be better to have them implemented in Algol 68 instead.  In
this case, however, it may be better to continue using the current
approach, as it allows inlining without requiring using LTO links.

Once we figure out the straightening (see below) then my hope is that we
can implement most if not all of the standard transput in Algol 68.

> (in passing, it seems to me that most operator definitions don't use case
> conformity but rather overloading instead).

Yeah I have the same perception, unless the value is an union itself.

> As to the business of using the definitions given in the Revised Report
> as-is, which is a step away from the wonderful sppp indicated above,I have
> a few concerns.
>
> First, there are two divisions per digit in subwhole, which is
> unnecessarily costly.  Also there is the repeated use of PLUSTO, creating a
> new string each time.
>
> I'm no expert at converting binary integers to printable UTF
> representations, but there are other algorithms out there that use bitwise
> manipulation to pass to from int to []string, for example "double-dabble"
> which uses shifts to go from binary integer to binary BCD, which can in
> turn be turned into []string by looking up each BCD digit in "0123456789".
> I've fiddled with double-dabble, just for fun, but for bigger integer
> values it starts to get complicated as there are too many bits to fit in an
> int or long int (for example, 2^31-1 requires 40 bits for its binary BCD
> representation).
>
> Given that printing numbers is a commonplace activity, it seems to me to be
> wise to look for efficiency where reasonable.
>
> Second, the fixed() and float() procedures operating on reals - given that
> Algol 68 predated the IEEE floating point standard, which is by and large
> what we have to deal with these days, it seems to me worthwhile revisiting
> the real conversion process.

This is just a first step.  I see no value in sticking to the
pseudocode-in-nature implementation in the Revised Report.  It is full
of typos anyway (I found two, and many others described in the algol
bulletins over the time.)

There is a much better transput implementation by van Vliet that I
intend to look at:

  https://www.dickgrune.com/CS/Algol68/TransputHansVanVliet

If you would like to contribute to the project with code, this may be
the opportunity for having an efficient and bug-free implementation of
the standard prelude :)

> In my own experiments, one thing that would be REALLY (sorry) nice to have
> would be an operator BIN that yields the bitwise representation of the
> floating point number.  This would greatly facilitate accurate conversions
> of the mantissa, which (again in my experiments) otherwise require the use
> of long real to convert real and long long real to convert long real
> (leaving us with what to convert long long real?) in order to get decent
> accuracy, which I define as results as close as possible to representations
> generated by C programs.

We can very easily add that operator to the extended prelude as a GNU
extension.  Should we do that?  In that case please prepare a proposal
for it that we can review and add to https://git.sr.ht/~jemarch/gnu68.

> Third, I guess sppp gives us the ability to define modes simplout and
> simplin, which if true is excellent news because it also offers us the
> potential to implement the operators STRAIGHTOUT and STRAIGHTIN as per
> §10.3.2.3 of the Revised Report.
>
> Having had my thread-stealing moment, I'm really glad to see this stuff
> happening, once again many many thanks and congratulations!


More information about the Algol68 mailing list