• Renaming primitives.

    From Blady@21:1/5 to All on Wed Jan 10 11:37:39 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Dmitry A. Kazakov@21:1/5 to Blady on Wed Jan 10 13:13:59 2024
    On 2024-01-10 11:37, Blady wrote:

    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?

    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Blady on Wed Jan 10 12:38:25 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Dmitry A. Kazakov on Wed Jan 10 20:09:57 2024
    "Dmitry A. Kazakov" <mailbox@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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Blady on Wed Jan 10 20:18:39 2024
    "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.

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blady@21:1/5 to All on Thu Jan 11 11:09:38 2024
    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 ?

    ...
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blady@21:1/5 to All on Thu Jan 11 11:06:45 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Jeffrey R.Carter@21:1/5 to Blady on Thu Jan 11 12:06:27 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Randy Brukardt@21:1/5 to Blady on Thu Jan 11 21:59:05 2024
    "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. :-).

    Randy.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From J-P. Rosen@21:1/5 to All on Fri Jan 12 05:47:41 2024
    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blady@21:1/5 to All on Fri Jan 12 11:29:40 2024
    Le 12/01/2024 à 04:59, Randy Brukardt a écrit :
    "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.

    Thanks, I like it.

    ...
    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. :-).

    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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Blady@21:1/5 to All on Fri Jan 12 11:42:19 2024
    Le 11/01/2024 à 11:09, Blady a écrit :
    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.

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

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)
  • From Lawrence D'Oliveiro@21:1/5 to J-P. Rosen on Fri Jan 12 23:36:07 2024
    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.

    --- SoupGate-Win32 v1.05
    * Origin: fsxNet Usenet Gateway (21:1/5)