Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Renaming primitives.

76 views
Skip to first unread message

Blady

unread,
Jan 10, 2024, 5:37:43 AMJan 10
to
Hello,

Is a procedure renaming equivalent to a simple call?
For instance:
procedure Log (Msg : String) is
begin
Ada.Text_IO.Put_Line (Msg);
end Log;
procedure My_Log_1 (Msg : String) is
begin
Log (Msg);
end My_Log_1;
procedure My_Log_2 (Msg : String) renames Log;

Almost, My_Log_1 is equivalent to My_Log_2, isn't it?

Is it the same with primitives?

For instance:
package Loggings is
type Logging is tagged record
Output : Ada.Text_IO.File_Access;
end record;
procedure Log (Handler : Logging; Msg : String);
end Loggings;
My_Handler : aliased Loggings.Logging := (Output =>
Ada.Text_IO.Current_Output);
My_Generic_Handler : access Loggings.Logging'Class := My_Handler'Access;
procedure My_Log_3 (Msg : String) renames My_Generic_Handler.Log;

To my surprise (well I hoped) My_Log_3 is compiled by GNAT.
Is it conformed to the Ada standard?

What is happening if My_Generic_Handler change?

For instance:
type Full_Logging is new Logging with null record;
procedure Log (Handler : Full_Logging; Msg : String);
...
My_Full_Handler : aliased Loggings.Full_Logging := (Output =>
Ada.Text_IO.Current_Output);
...
My_Generic_Handler := My_Full_Handler'Access;

Well, logically (?), My_Log_3 follows the change and outputs with
Full_Logging.

Unfortunately, GNAT claims renaming with several parameters.
I add:
procedure Log (Handler : Logging; Msg : String; Err : Natural);
...
procedure My_Log_4 (Msg : String; Err : Natural) renames
My_Generic_Handler.Log;

I got:
test_20240110_renproc.adb:47:14: error: too many arguments in call to "log"

Is it a correct or a GNAT issue?

Full source code on demand.

Thanks.
Happy New Year to all!
Pascal.

Jeffrey R.Carter

unread,
Jan 10, 2024, 6:38:28 AMJan 10
to
On 2024-01-10 11:37, Blady wrote:
>
>    package Loggings is
>       type Logging is tagged record
>          Output : Ada.Text_IO.File_Access;
>       end record;
>       procedure Log (Handler : Logging; Msg : String);
>    end Loggings;
>    My_Handler : aliased Loggings.Logging := (Output => Ada.Text_IO.Current_Output);
>    My_Generic_Handler : access Loggings.Logging'Class := My_Handler'Access;
>    procedure My_Log_3 (Msg : String) renames My_Generic_Handler.Log;

My_Generic_Handler.Log is shorthand for My_Generic_Handler.all.Log. According to
AARM 8.5.4(5.e/5) (http://www.ada-auth.org/standards/22aarm/html/AA-8-5-4.html),
the renaming also renames the prefixing object and passes it to calls to the
renamed subprogram: "The prefix in such a case is essentially renamed and passed
to any calls of the renamed subprogram."

So if I understand this correctly the renaming is roughly equivalent to

<anonymous> : Loggings.Logging renames My_Generic_Handler.all;
procedure My_Log_3 (Handler : Loggings.Logging := <anonymous>; Msg : String)
renames Loggings.Logging.Log;

except that My_Log_3 is called with only a String parameter even when using
positional notation.

Another way to look at it is that

My_Log_3 ("msg");

is implemented as

<anonymous>.Log (Msg => "msg");

> What is happening if My_Generic_Handler change?
>
>       type Full_Logging is new Logging with null record;
>       procedure Log (Handler : Full_Logging; Msg : String);
> ...
>    My_Full_Handler : aliased Loggings.Full_Logging := (Output =>
> Ada.Text_IO.Current_Output);
> ...
>    My_Generic_Handler := My_Full_Handler'Access;
>
> Well, logically (?), My_Log_3 follows the change and outputs with Full_Logging.

No, My_Log_3 continues to call Log with My_Handler as the object, IIUC.

> Unfortunately, GNAT claims renaming with several parameters.
> I add:
>       procedure Log (Handler : Logging; Msg : String; Err : Natural);
> ...
>    procedure My_Log_4 (Msg : String; Err : Natural) renames
> My_Generic_Handler.Log;
>
> I got:
> test_20240110_renproc.adb:47:14: error: too many arguments in call to "log"
>
> Is it a correct or a GNAT issue?

I'm not sure what is going on here. This looks correct to me.

--
Jeff Carter
"Fundamental improvements in performance
are most often made by algorithm changes,
not by tuning."
Elements of Programming Style
201

Dmitry A. Kazakov

unread,
Jan 10, 2024, 7:14:03 AMJan 10
to
On 2024-01-10 11:37, Blady wrote:

This looks like a bug to me. ARM 8.5.4 (2/3) states that the right part
of "renames" must be a name of a callable entity. My_Generic_Handler.Log
is a procedure call which is not a callable entity name.

Renaming a callable result of a function call might be legal [and quite
funny].

Disclaimer. I am not a language lawyer.

P.S. Specialization of subprograms would be a nice feature, though.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de

Randy Brukardt

unread,
Jan 10, 2024, 9:09:30 PMJan 10
to
"Dmitry A. Kazakov" <mai...@dmitry-kazakov.de> wrote in message
news:unm1m6$2ftcd$1...@dont-email.me...
> On 2024-01-10 11:37, Blady wrote:
...
>> To my surprise (well I hoped) My_Log_3 is compiled by GNAT.
>> Is it conformed to the Ada standard?
>
> This looks like a bug to me. ARM 8.5.4 (2/3) states that the right part of
> "renames" must be a name of a callable entity. My_Generic_Handler.Log is a
> procedure call which is not a callable entity name.

A "prefixed view" is indeed a view of a callable entity. For instance, you
can pass those as generic formal subprograms or rename them.

> Renaming a callable result of a function call might be legal [and quite
> funny].

I believe that is legal as well.

> Disclaimer. I am not a language lawyer.

I'll refrain from a pithy remark. ;-)

> P.S. Specialization of subprograms would be a nice feature, though.

And Ada has had a limited form of it since Ada 2005. Limited because you can
only eliminate the first parameter. (Of course, you can also eliminate the
first two parameters, and so on. But you can't eliminate the third
parameter, although you can default it and effectively eliminate from calls.
Note that a renaming can change the defaults used for a subprogram call.)

Randy.


Randy Brukardt

unread,
Jan 10, 2024, 9:18:11 PMJan 10
to
"Blady" <p....@orange.fr> wrote in message
news:unls1j$2f0up$3...@dont-email.me...
> Is a procedure renaming equivalent to a simple call?

General point: "Equivalent" is never true in programming language design. If
construct A is equivalent in every way to construct B, then they have to be
the same construct.

For instance, in your example below, the two subprogram declarations have
different identifiers which have different visibility (two declarations
cannot be at exactly the same place), so there is at least one way that
they're not equivalent.

So, if you want to talk about "equivalence", you need to qualify that by
what properties you are interested in.

...
> What is happening if My_Generic_Handler change?

Nothing. The names in a renaming are evaluated when the renaming is
declared. If there are parts that could change, the compiler has to save the
values at the point of the renaming. That's true for all forms of renaming
(some names, like package names, can't change meaning so the example isn't
possible, of course).

...
> I got:
> test_20240110_renproc.adb:47:14: error: too many arguments in call to
> "log"
>
> Is it a correct or a GNAT issue?

Looks like a bug to me. Not too surprising, though, this sort of thing is a
special case in a compiler and often added to pass an ACATS test or user bug
report. Such fixes can often not be fully general.

Randy.


Blady

unread,
Jan 11, 2024, 5:06:50 AMJan 11
to
Le 10/01/2024 à 12:38, Jeffrey R.Carter a écrit :
> On 2024-01-10 11:37, Blady wrote:
>>     procedure My_Log_3 (Msg : String) renames My_Generic_Handler.Log;
>
> My_Generic_Handler.Log is shorthand for My_Generic_Handler.all.Log.
> According to AARM 8.5.4(5.e/5)
> (http://www.ada-auth.org/standards/22aarm/html/AA-8-5-4.html), the
> renaming also renames the prefixing object and passes it to calls to the
> renamed subprogram: "The prefix in such a case is essentially renamed
> and passed to any calls of the renamed subprogram."
>
> So if I understand this correctly the renaming is roughly equivalent to
>
> <anonymous> : Loggings.Logging renames My_Generic_Handler.all;
> procedure My_Log_3 (Handler : Loggings.Logging := <anonymous>; Msg :
> String) renames Loggings.Logging.Log;
>
> except that My_Log_3 is called with only a String parameter even when
> using positional notation.
>
> Another way to look at it is that
>
>    My_Log_3 ("msg");
>
> is implemented as
>
>    <anonymous>.Log (Msg => "msg");

Thanks for your useful explanation.

> > What is happening if My_Generic_Handler change?
> >
>>        type Full_Logging is new Logging with null record;
>>        procedure Log (Handler : Full_Logging; Msg : String);
>> ...
>>     My_Full_Handler : aliased Loggings.Full_Logging := (Output =>
>> Ada.Text_IO.Current_Output);
>> ...
>>     My_Generic_Handler := My_Full_Handler'Access;
>>
>> Well, logically (?), My_Log_3 follows the change and outputs with
>> Full_Logging.
>
> No, My_Log_3 continues to call Log with My_Handler as the object, IIUC.

Yet, the code:
My_Log_3 ("Hei");
My_Generic_Handler := My_Full_Handler'Access;
My_Log_3 ("Hei");
gives:
Hei
Full Hei

I thought that was correct, wasn't it?

Pascal.

Blady

unread,
Jan 11, 2024, 5:09:42 AMJan 11
to
Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
> "Blady" <p....@orange.fr> wrote in message
> news:unls1j$2f0up$3...@dont-email.me...
>> Is a procedure renaming equivalent to a simple call?
>
> General point: "Equivalent" is never true in programming language design. If
> construct A is equivalent in every way to construct B, then they have to be
> the same construct.
>
> For instance, in your example below, the two subprogram declarations have
> different identifiers which have different visibility (two declarations
> cannot be at exactly the same place), so there is at least one way that
> they're not equivalent.
>
> So, if you want to talk about "equivalence", you need to qualify that by
> what properties you are interested in.

Well, I hadn't find a better word :-(

> ...
>> What is happening if My_Generic_Handler change?
>
> Nothing. The names in a renaming are evaluated when the renaming is
> declared. If there are parts that could change, the compiler has to save the
> values at the point of the renaming. That's true for all forms of renaming
> (some names, like package names, can't change meaning so the example isn't
> possible, of course).

Yet, the code:
My_Log_3 ("Hei");
My_Generic_Handler := My_Full_Handler'Access;
My_Log_3 ("Hei");
gives:
Hei
Full Hei

I thought that was correct, wasn't it?
GNAT issue ?

> ...
>> I got:
>> test_20240110_renproc.adb:47:14: error: too many arguments in call to
>> "log"
>>
>> Is it a correct or a GNAT issue?
>
> Looks like a bug to me. Not too surprising, though, this sort of thing is a
> special case in a compiler and often added to pass an ACATS test or user bug
> report. Such fixes can often not be fully general.

Thanks, I'll report it.

Pascal.


Jeffrey R.Carter

unread,
Jan 11, 2024, 6:06:30 AMJan 11
to
On 2024-01-11 11:06, Blady wrote:
>
> Yet, the code:
>    My_Log_3 ("Hei");
>    My_Generic_Handler := My_Full_Handler'Access;
>    My_Log_3 ("Hei");
> gives:
> Hei
> Full Hei
>
> I thought that was correct, wasn't it?

Not according to my understanding, and it seems according to Brukardt's
better-informed understanding.

--
Jeff Carter
"[A] brilliant military career that after thirty
years catapulted him to the rank of corporal."
Take the Money and Run
138

Randy Brukardt

unread,
Jan 11, 2024, 10:58:14 PMJan 11
to
"Blady" <p....@orange.fr> wrote in message
news:unoep3$2uqo6$2...@dont-email.me...
> Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
>> "Blady" <p....@orange.fr> wrote in message
>> news:unls1j$2f0up$3...@dont-email.me...
>>> Is a procedure renaming equivalent to a simple call?
>>
>> General point: "Equivalent" is never true in programming language design.
>> If
>> construct A is equivalent in every way to construct B, then they have to
>> be
>> the same construct.
>>
>> For instance, in your example below, the two subprogram declarations have
>> different identifiers which have different visibility (two declarations
>> cannot be at exactly the same place), so there is at least one way that
>> they're not equivalent.
>>
>> So, if you want to talk about "equivalence", you need to qualify that by
>> what properties you are interested in.
>
> Well, I hadn't find a better word :-(

You have to say something like "equivalent in run-time behavior";
"equivalent" by itself is always False.

>> ...
>>> What is happening if My_Generic_Handler change?
>>
>> Nothing. The names in a renaming are evaluated when the renaming is
>> declared. If there are parts that could change, the compiler has to save
>> the
>> values at the point of the renaming. That's true for all forms of
>> renaming
>> (some names, like package names, can't change meaning so the example
>> isn't
>> possible, of course).
>
> Yet, the code:
> My_Log_3 ("Hei");
> My_Generic_Handler := My_Full_Handler'Access;
> My_Log_3 ("Hei");
> gives:
> Hei
> Full Hei
>
> I thought that was correct, wasn't it?

Shouldn't be correct. The "name" is evaluated during a renaming, and the
renamed entity does not change afterwards. So whatever subprogram My_Log_3
designates for the first call should be the same for the second call.

> GNAT issue ?

Appears to be (of course, without seeing the full code I can't say
definitively; people here often post snippets that aren't quite the same as
the actual code they tried to run. I wouldn't expect that with you, but we
all make mistakes. :-).

Randy.


J-P. Rosen

unread,
Jan 12, 2024, 4:47:45 AMJan 12
to
Le 11/01/2024 à 23:59, Randy Brukardt a écrit :
> Shouldn't be correct. The "name" is evaluated during a renaming, and the
> renamed entity does not change afterwards. So whatever subprogram My_Log_3
> designates for the first call should be the same for the second call.

Just to make things perfectly clear (I hope):
Renames shouldn't be seen as a kind of macro (i.e. textual substitution
of the LHS by the RHS). It is rather like evaluating the address of the
RHS thing, and storing it into the LHS. A kind of precalculated
address/pointer/reference.

--
J-P. Rosen
Adalog
2 rue du Docteur Lombard, 92441 Issy-les-Moulineaux CEDEX
https://www.adalog.fr https://www.adacontrol.fr

Blady

unread,
Jan 12, 2024, 5:29:45 AMJan 12
to
Le 12/01/2024 à 04:59, Randy Brukardt a écrit :
> "Blady" <p....@orange.fr> wrote in message
> news:unoep3$2uqo6$2...@dont-email.me...
>> Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
>>> "Blady" <p....@orange.fr> wrote in message
>>> news:unls1j$2f0up$3...@dont-email.me...
>>>> Is a procedure renaming equivalent to a simple call?
>>>
>>> General point: "Equivalent" is never true in programming language design.
>>> If
>>> construct A is equivalent in every way to construct B, then they have to
>>> be
>>> the same construct.
>>>
>>> For instance, in your example below, the two subprogram declarations have
>>> different identifiers which have different visibility (two declarations
>>> cannot be at exactly the same place), so there is at least one way that
>>> they're not equivalent.
>>>
>>> So, if you want to talk about "equivalence", you need to qualify that by
>>> what properties you are interested in.
>>
>> Well, I hadn't find a better word :-(
>
> You have to say something like "equivalent in run-time behavior";
> "equivalent" by itself is always False.

Thanks, I like it.
I quote you :-) and attached the full source code.
You might follow or comment on the created issue:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113350

Blady

unread,
Jan 12, 2024, 5:42:22 AMJan 12
to
Le 11/01/2024 à 11:09, Blady a écrit :
> Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
>> "Blady" <p....@orange.fr> wrote in message
>> news:unls1j$2f0up$3...@dont-email.me...
>>> I got:
>>> test_20240110_renproc.adb:47:14: error: too many arguments in call to
>>> "log"
>>>
>>> Is it a correct or a GNAT issue?
>>
>> Looks like a bug to me. Not too surprising, though, this sort of thing
>> is a
>> special case in a compiler and often added to pass an ACATS test or
>> user bug
>> report. Such fixes can often not be fully general.
>
> Thanks, I'll report it.

Submitted issue with attached source code:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113351

Lawrence D'Oliveiro

unread,
Jan 12, 2024, 6:36:11 PMJan 12
to
On Fri, 12 Jan 2024 05:47:41 -0400, J-P. Rosen wrote:

> Renames shouldn't be seen as a kind of macro (i.e. textual substitution
> of the LHS by the RHS).

There is the wrong way of implementing macros--by textual substitution--
and there is the right way, as done in homoiconic languages such as Lisp.

For example, the latter can give you lexical binding. That is, the rename
still refers to the original definition, even in an inner scope where that
is masked by another entity with the same name. I assume that is how the
Ada mechanism works.
0 new messages