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?
  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;
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.
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?
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.
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.
Is a procedure renaming equivalent to a simple call?
What is happening if My_Generic_Handler change?
I got:
test_20240110_renproc.adb:47:14: error: too many arguments in call to
"log"
Is it a correct or a GNAT issue?
"Blady" <p.p11@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.
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");
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?
Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
"Blady" <p.p11@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 ?
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.
"Blady" <p.p11@orange.fr> wrote in message news:unoep3$2uqo6$2@dont-email.me...
Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
"Blady" <p.p11@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. :-).
Le 11/01/2024 à 03:18, Randy Brukardt a écrit :
"Blady" <p.p11@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.
Renames shouldn't be seen as a kind of macro (i.e. textual substitution
of the LHS by the RHS).
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 379 |
Nodes: | 16 (2 / 14) |
Uptime: | 45:00:08 |
Calls: | 8,141 |
Calls today: | 4 |
Files: | 13,085 |
Messages: | 5,858,057 |