comp.lang.ada
 help / color / mirror / Atom feed
* Loss of visibility of class-wide operation in prefix notation
@ 2014-04-05 15:09 Natasha Kerensikova
  2014-04-07 15:30 ` Adam Beneschan
  0 siblings, 1 reply; 2+ messages in thread
From: Natasha Kerensikova @ 2014-04-05 15:09 UTC (permalink / raw)


Hello,

I have been encountering some strange behavior of GNAT, and I wonder
whether it's a compiler bug or whether I'm doing something illegal.

Please consider the following code, it's a bit long but hopefully clear
enough:


package Root_Interface is

   type T is interface;

   procedure Process (Self : in out T; Result : out Boolean) is abstract;

   procedure Process (Self : in out T'Class);
      --  Call Process and discard Result

end Root_Interface;


package body Root_Interface is

   procedure Process (Self : in out T'Class) is
      Result : Boolean;
   begin
      Process (Self, Result);
   end Process;

end Root_Interface;


package Root_Interface.Extension is

   type T is interface and Root_Interface.T;

   procedure Self_Check (Self : in out T) is abstract;

end Root_Interface.Extension;



with Root_Interface.Extension;

package Root_Interface.Half_Implementation is

   type T is abstract new Extension.T with private;

   not overriding procedure Subprocess (Self : in out T) is abstract;

   overriding procedure Process (Self : in out T; Result : out Boolean);
   overriding procedure Self_Check (Self : in out T);

   type Example is new Extension.T with private;

private

   type T is abstract new Extension.T with null record;

   type Example is new T with record
      Count : Natural := 0;
   end record;

   overriding procedure Subprocess (Self : in out Example);

end Root_Interface.Half_Implementation;


package body Root_Interface.Half_Implementation is

   overriding procedure Process (Self : in out T; Result : out Boolean) is
   begin
      Subprocess (T'Class (Self));
      Result := True;
   end Process;


   overriding procedure Self_Check (Self : in out T) is
   begin
      raise Program_Error;
   end Self_Check;


   overriding procedure Subprocess (Self : in out Example) is
   begin
      Self.Count := Self.Count + 1;
   end Subprocess;

end Root_Interface.Half_Implementation;


package Root_Interface.Half_Implementation.Tests is

   procedure Test_Suite;

end Root_Interface.Half_Implementation.Tests;


package body Root_Interface.Half_Implementation.Tests is

   procedure Test_Suite is
      Object : Example;
   begin
      Object.Process;
   end Test_Suite;

end Root_Interface.Half_Implementation.Tests;



The basic idea is that I have a general root abstract type, used by most
clients of the library, with an optional extension. Then in a specific
of set of situations I can massively refactor the code, which leads to
the abstract "half-implementation", the other (mush smaller) half being
provided in concrete types by overriding the abstract primitive. In the
same package I also provide a basic concrete type, as an example to make
the code more self-documenting and to be used in the test suite.
The test suite itself is in a child package so that it can peek into the
implementation for whitebox tests.

So far everything is fine, and GNAT-AUX 4.9.0 compiles it happily.

But now I realize I need user-defined finalization in a concrete type
which inherits from Root_Interface.Half_Implementation.T, so I change it
to derive from Ada.Finalization.Controlled, without overriding anything:



with Ada.Finalization;

with Root_Interface.Extension;

package Root_Interface.Half_Implementation is

   type T is abstract new Ada.Finalization.Controlled and Extension.T
     with private;

   not overriding procedure Subprocess (Self : in out T) is abstract;

   overriding procedure Process (Self : in out T; Result : out Boolean);
   overriding procedure Self_Check (Self : in out T);

   type Example is new Extension.T with private;

private

   type T is abstract new Ada.Finalization.Controlled and Extension.T
     with null record;

   type Example is new T with record
      Count : Natural := 0;
   end record;

   overriding procedure Subprocess (Self : in out Example);

end Root_Interface.Half_Implementation;



And suddenly, GNAT rejects the test suite:
Compiling: root_interface-half_implementation-tests.adb
(source file time stamp: 2014-04-05 14:51:26)

     6.       Object.Process;
                    |
        >>> missing argument for parameter "Result" in call to "Process"
ted) at root_interface-half_implementation.ads:15


However, when switching to traditional notation "Process (Object);"
everything is still fine. Moreover, when
Root_Interface.Half_Implementation.T implements Root_Interface.T rather
than the extension, everything still works fine.


Would you have any idea what I am doing wrong?



Thanks for your help,
Natasha

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Loss of visibility of class-wide operation in prefix notation
  2014-04-05 15:09 Loss of visibility of class-wide operation in prefix notation Natasha Kerensikova
@ 2014-04-07 15:30 ` Adam Beneschan
  0 siblings, 0 replies; 2+ messages in thread
From: Adam Beneschan @ 2014-04-07 15:30 UTC (permalink / raw)


On Saturday, April 5, 2014 8:09:07 AM UTC-7, Natasha Kerensikova wrote:
> Hello,
> 
> I have been encountering some strange behavior of GNAT, and I wonder
> whether it's a compiler bug or whether I'm doing something illegal.

It appears to be a compiler bug.  The "procedure Process (Self : in out T'Class)" should meet the requirements of 3.4.1(9.2) for "object.operation" notation.  In any event, adding a new Ada.Finalization parent type shouldn't affect the legality (since Ada.Finalization does not have any primitive subprograms named Process). 

                              -- Adam


> 
> 
> 
> Please consider the following code, it's a bit long but hopefully clear
> 
> enough:
> 
> 
> 
> 
> 
> package Root_Interface is
> 
> 
> 
>    type T is interface;
> 
> 
> 
>    procedure Process (Self : in out T; Result : out Boolean) is abstract;
> 
> 
> 
>    procedure Process (Self : in out T'Class);
> 
>       --  Call Process and discard Result
> 
> 
> 
> end Root_Interface;
> 
> 
> 
> 
> 
> package body Root_Interface is
> 
> 
> 
>    procedure Process (Self : in out T'Class) is
> 
>       Result : Boolean;
> 
>    begin
> 
>       Process (Self, Result);
> 
>    end Process;
> 
> 
> 
> end Root_Interface;
> 
> 
> 
> 
> 
> package Root_Interface.Extension is
> 
> 
> 
>    type T is interface and Root_Interface.T;
> 
> 
> 
>    procedure Self_Check (Self : in out T) is abstract;
> 
> 
> 
> end Root_Interface.Extension;
> 
> 
> 
> 
> 
> 
> 
> with Root_Interface.Extension;
> 
> 
> 
> package Root_Interface.Half_Implementation is
> 
> 
> 
>    type T is abstract new Extension.T with private;
> 
> 
> 
>    not overriding procedure Subprocess (Self : in out T) is abstract;
> 
> 
> 
>    overriding procedure Process (Self : in out T; Result : out Boolean);
> 
>    overriding procedure Self_Check (Self : in out T);
> 
> 
> 
>    type Example is new Extension.T with private;
> 
> 
> 
> private
> 
> 
> 
>    type T is abstract new Extension.T with null record;
> 
> 
> 
>    type Example is new T with record
> 
>       Count : Natural := 0;
> 
>    end record;
> 
> 
> 
>    overriding procedure Subprocess (Self : in out Example);
> 
> 
> 
> end Root_Interface.Half_Implementation;
> 
> 
> 
> 
> 
> package body Root_Interface.Half_Implementation is
> 
> 
> 
>    overriding procedure Process (Self : in out T; Result : out Boolean) is
> 
>    begin
> 
>       Subprocess (T'Class (Self));
> 
>       Result := True;
> 
>    end Process;
> 
> 
> 
> 
> 
>    overriding procedure Self_Check (Self : in out T) is
> 
>    begin
> 
>       raise Program_Error;
> 
>    end Self_Check;
> 
> 
> 
> 
> 
>    overriding procedure Subprocess (Self : in out Example) is
> 
>    begin
> 
>       Self.Count := Self.Count + 1;
> 
>    end Subprocess;
> 
> 
> 
> end Root_Interface.Half_Implementation;
> 
> 
> 
> 
> 
> package Root_Interface.Half_Implementation.Tests is
> 
> 
> 
>    procedure Test_Suite;
> 
> 
> 
> end Root_Interface.Half_Implementation.Tests;
> 
> 
> 
> 
> 
> package body Root_Interface.Half_Implementation.Tests is
> 
> 
> 
>    procedure Test_Suite is
> 
>       Object : Example;
> 
>    begin
> 
>       Object.Process;
> 
>    end Test_Suite;
> 
> 
> 
> end Root_Interface.Half_Implementation.Tests;
> 
> 
> 
> 
> 
> 
> 
> The basic idea is that I have a general root abstract type, used by most
> 
> clients of the library, with an optional extension. Then in a specific
> 
> of set of situations I can massively refactor the code, which leads to
> 
> the abstract "half-implementation", the other (mush smaller) half being
> 
> provided in concrete types by overriding the abstract primitive. In the
> 
> same package I also provide a basic concrete type, as an example to make
> 
> the code more self-documenting and to be used in the test suite.
> 
> The test suite itself is in a child package so that it can peek into the
> 
> implementation for whitebox tests.
> 
> 
> 
> So far everything is fine, and GNAT-AUX 4.9.0 compiles it happily.
> 
> 
> 
> But now I realize I need user-defined finalization in a concrete type
> 
> which inherits from Root_Interface.Half_Implementation.T, so I change it
> 
> to derive from Ada.Finalization.Controlled, without overriding anything:
> 
> 
> 
> 
> 
> 
> 
> with Ada.Finalization;
> 
> 
> 
> with Root_Interface.Extension;
> 
> 
> 
> package Root_Interface.Half_Implementation is
> 
> 
> 
>    type T is abstract new Ada.Finalization.Controlled and Extension.T
> 
>      with private;
> 
> 
> 
>    not overriding procedure Subprocess (Self : in out T) is abstract;
> 
> 
> 
>    overriding procedure Process (Self : in out T; Result : out Boolean);
> 
>    overriding procedure Self_Check (Self : in out T);
> 
> 
> 
>    type Example is new Extension.T with private;
> 
> 
> 
> private
> 
> 
> 
>    type T is abstract new Ada.Finalization.Controlled and Extension.T
> 
>      with null record;
> 
> 
> 
>    type Example is new T with record
> 
>       Count : Natural := 0;
> 
>    end record;
> 
> 
> 
>    overriding procedure Subprocess (Self : in out Example);
> 
> 
> 
> end Root_Interface.Half_Implementation;
> 
> 
> 
> 
> 
> 
> 
> And suddenly, GNAT rejects the test suite:
> 
> Compiling: root_interface-half_implementation-tests.adb
> 
> (source file time stamp: 2014-04-05 14:51:26)
> 
> 
> 
>      6.       Object.Process;
> 
>                     |
> 
>         >>> missing argument for parameter "Result" in call to "Process"
> 
> ted) at root_interface-half_implementation.ads:15
> 
> 
> 
> 
> 
> However, when switching to traditional notation "Process (Object);"
> 
> everything is still fine. Moreover, when
> 
> Root_Interface.Half_Implementation.T implements Root_Interface.T rather
> 
> than the extension, everything still works fine.
> 
> 
> 
> 
> 
> Would you have any idea what I am doing wrong?
> 
> 
> 
> 
> 
> 
> 
> Thanks for your help,
> 
> Natasha



^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2014-04-07 15:30 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-04-05 15:09 Loss of visibility of class-wide operation in prefix notation Natasha Kerensikova
2014-04-07 15:30 ` Adam Beneschan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox