[RFC] Symbol mangling schema

Jose E. Marchesi jemarch@gnu.org
Sun Nov 9 22:51:43 GMT 2025


Hello Chris.

> José and list,
>
> Another thought or two below...
>
>
> On Sun, Nov 9, 2025, 10:03 Jose E. Marchesi <jemarch@gnu.org> wrote:
>
>>
>> Hello people!
>>
>> The implementation of modules and separated compilation is progressing
>> steadily:
>>
>>   $ cat module.a68
>>   module Foo =
>>   def int i;
>>       int j = 20;
>>       proc ticks = void: to i do puts ("tick'n") od;
>>       i := 5
>>   postlude
>>     ticks
>>   fed
>>   $ cat foo.c
>>   #include <stdio.h>
>>
>>   void __FOO_prelude (void);
>>   void __FOO_postlude (void);
>>
>>   extern void ticks (void);
>>   extern int i;
>>   extern int j;
>>
>>   void
>>   __algol68_main ()
>>   {
>>     __FOO_prelude ();
>>     ticks ();
>>     i = 3;
>>     printf ("j: %d\n", j);
>>     __FOO_postlude ();
>>   }
>>   $ ga68 -c module.a68
>>   $ gcc -c foo.c
>>   $ ga68 module.o foo.o -lga68
>>   $ ./a.out
>>   tick
>>   tick
>>   tick
>>   tick
>>   tick
>>   j: 20
>>   tick
>>   tick
>>   tick
>>
>> Now it is time to decide on a schema for mangling our symbols.  In my
>> opinion the schema shall fullfil the following desirable properties:
>>
>> - It shall be as simple and orthogonal as possible.  In particular, the
>>   meaning of symbols shall not depend on their positions.
>>
>> - It shall lead to readable (by humans) and predictable symbol names.
>>   It shouldn't be necessary for a programmer to use a tool in order to
>>   figure out the mangled symbol for some given construct.  For example,
>>   it is immediate to figure out that the symbol corresponding to an
>>   identifier "accountant" defined in a module "Foo" is FOO_accountant.
>>
>> - The mangling schema shall be as much as compiler-independent as
>>   possible.
>>
>> So this is my proposal:
>>
>> 1. Symbols used internally do not follow any fixed mangling rule.
>>
>> 2. The main program symbol is __algol68_main.
>>
>> 3. Bold words, i.e. mode indicants, module indicants and operator
>>    indicants are mangled to upper-case letters and normal digits.  Note
>>    that the underscores following taggles supported by the stropping
>>    regimes are not part of the indicants, and therefore are not conveyed
>>    to mangled symbols.  For example, a mode "Tree_Node" is mangled to
>>    TREENODE.
>>
>> 4. Tags, i.e. identifiers, are mangled to lower-case and normal digits.
>>    Again, underscores following taggles are not part of the tag proper,
>>    and are not conveyed to mangled symbols.  Fo example, the identifier
>>    "remove_row" is mangled to removerow.
>>
>> 5. Symbols corresponding to publicized identifiers and indicants always
>>    start with the name of the definition module publicizing them,
>>    followed by an underscore character.  For example, in the module:
>>
>>      module Json =
>>      def
>>          pub mode JSON_Val = union
>> (void,bool,int,string.JSON_Arr,JSON_Obj),
>>          pub mode JSON_Arr = struct (JSON_Elm elements),
>>          ...;
>>
>>          pub proc json_new_obj = JSON_Val: heap JSON_Obj;
>>          ...
>>      fed
>>
>>    The mode JSON_Val will mangle to a symbol JSON_JSONVAL.
>>    The identifier json_new_obj will mangle to a symbol JSON_jsonnewobj.
>>
>> 6. Publicized symbols that are intended to be used by the compiler or
>>    runtime are preceded by the mangled name of the module followed by
>>    two underscore characters.  For example, the prelude and postlude for
>>    the above module will be accessible via the mangled symbols
>>    JSON__prelude and JSON__postlude.
>>
>> 7. Operator symbols, the monads and nomads, are mangled to letter codes
>>    symbolizing the symbols:
>>
>>      %    (p)ercentage
>>      ^    (c)aret
>>      &    (a)mpersand
>>      +    (p)lus
>>      -    (m)inus
>>      ~    (t)ilde
>>      !    (b)ang
>>      ?    (q)uestion mark
>>      >    bi(g)ger than
>>      <    (l)ess than
>>      /    (s)lash
>>      =    (e)qual
>>      :    c(o)lon
>>      *    sta(r)
>>
>>    Each letter code is followed by a single underscore character.  So
>>    for example, in the following module:
>>
>>      module Foo =
>>      def
>>          int ss;
>>          op // = (int a, b) int: a + b;
>>          ...
>>      fed
>>
>>    The identifier ss will mangle to a symbol FOO_ss.
>>    The operator // will mangle to a symbol FOO_s_s_.
>>
>> And that's basically it.
>> WDYT?
>>
>
> After thinking about Jose's response on operator priorities and reading the
> conversation about operator name mangling, I wonder if it's worth
> considering whether the scheme for dealing with overloaded operators could
> be extended to procedures or if there is something missing.
>
> This "just in case" someone decides to add procedure overloading down the
> road.

The same mangling strategy used in operators could be used I think.  For
example to add a per-module unique identifier (like a counter) to the
exported symbols.

> In the same spirit, would it be worthwhile thinking about how this scheme
> fits with parametrized types, in case those get added later?

As I understand Lindsey's sketch, modals are effectively mode values,
i.e. values that are modes and themselves are of some (meta)mode.  As
such, I don't think supporting modals will require changes in the symbol
mangling, unless we decide to encode modes in symbols, and I really
think that's not the best way to proceed... at least I think that for
now :)

> Another question that seems obvious is can we have / do we want to have a
> hierarchical name space for modules, something like
> org.ga68.collections.list?

I personally don't like that sort of external namespace structuring, but
that is just a personal opinion, so that is indeed a discussion to have.

> And the last thing that comes to mind is the OUTTYPE and INTYPE business we
> see in transput (and may want elsewhere, depending on how parametrized
> types work out) - given that it's not possible to declare MODE OUTTYPE in
> Algol68, how could it be exported from a module?
>
> I'm specifically thinking of the Aleph and longsetys but also the way that
> for example print() is able to unpack structures and rows of rows and such.
> I realize that I am confused as to how much of that unpacking is handled as
> code generation vs by some (unnamed?) procedure that "flattens" complex
> structures dynamically.

Hmm, for OUTTYPE and INTYPE, we can always add new fundamental modes to
the module interface... there are currently 243 free slots.  Again, that
wouldn't have an impact on the mangling unless we encode modes in
symbols.  This is actually another reason on why not doing that..

As for straightening... that is done at compile time (generation of code
that straightens a given mode) and I think it could be accomodated in
the module interface, but I would need to think about the details.  The
ALGOL68-RS compiler implements a very interesting extension, which is
the straightening coercion, that I definitely will explore and maybe
incorporate as a GNU extension.pp

> Of course it may be best to leave these kind of things for the next version
> of modules...

:) Thanks for the feedback!



More information about the Algol68 mailing list