comp.lang.ada
 help / color / mirror / Atom feed
* Indirect visibility of private part in child packages
@ 2009-06-04  5:45 Hibou57 (Yannick Duchêne)
  2009-06-04  7:50 ` Ludovic Brenta
  2009-06-04 16:06 ` Adam Beneschan
  0 siblings, 2 replies; 7+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-06-04  5:45 UTC (permalink / raw)


Hi all,

I've meet a tortuous question with a set of packages I'm converting
from Pascal (as I use Ada now, I'm taking the opportunity to re-create
a nicer design).

The question I'm facing deals with visibility of private part in child
package. More precisely, an indirect visibility of a private part. An
exemple will better show the case:

This can be reduced to three package (specs and bodies)

The root package:

>>>>> --------------------------------------------------
package P1 is
   type T1_Type is tagged private;
   -- Some primitives on T1_Type are specified here ...
private
   type T1_Type is tagged record
      Low_Level_Data : Some_Type;
   end record; -- T1_Type
end P1;
<<<<< --------------------------------------------------

The first child package (with this one, every thing's Ok):
>>>>> --------------------------------------------------
package P1.P2 is
   type T2_Type is new T1_Type with private;
   -- Some primitives on T2_Type are specified here ...
   procedure A_Primitive (Item : out T2_Type);
private
   type T2_Type is new T1_Type with null record;
end P1.P2;

package body P1.P2 is
   procedure A_Primitive (Item : out T2_Type) is
   begin
      Item.Low_Level_Data := ...;
      -- It works, beceause P1.P2 is a child
      -- package with a view on P1's private part
   end A_Primitive;
end P1.P2;
<<<<< --------------------------------------------------

The second child package (the one which turns into a subtile doubt):
>>>>> --------------------------------------------------
with P1.P2;
package P1.P3 is
   type T3_Type is new P1.P2.T2_Type with private;
   -- Some primitives on T2_Type are specified here ...
   procedure A_Primitive (Item : out T3_Type);
private
   type T3_Type is new P1.P2.T2_Type with null record;
end P1.P3;

package body P1.P3 is
   procedure A_Primitive (Item : out T3_Type) is
   begin
      Item.Low_Level_Data := ...;
      -- It fails : the compiler complains there is no
      -- selector "Low_Level_Data" defined for T3_Type
   end A_Primitive;
end P1.P3;
<<<<< --------------------------------------------------

As said in the last comment, it seems P1.P3 cannot see the
T1_Type.Low_Level_Data member. But as P3 is a child package of P1, it
has a view on P1's private part, and there is indeed no trouble about
it with P2. P3 know P2.T2_Type is derived from P1.T1_Type, and P3 has
a view on T1_Type privates. But it seems the compiler does not care
about it.

There may be interpretation matter here : does the private
specification, means "disallow access to private part" or does it
means "do not provide an access to the private part". If it means
"disallow access to private part", then it ill explain why P3 cannot
access T1_Type.Low_Level_Data member. But if it means "do no provide
an access to private" part, then P3 should still be able to access
T1.Low_Level_Data, beceause it has an access to this as a child
package of P1.

What does long experienced lawyers think about it ?

I've try to look in section 8 of the "RM 2005", but either the answer
was not there or else, I missed it.

Note #1: I hope my exemple is clear enought. If it is not, please,
tell me, so that I can attempt to reword it.

Note #2: I do not want to make P3 a child package of P2, beceause it
does not need to access any internals of T2_Type. I want to have some
types, extending each others, and doing so only relying on either
public interface or on the sole common private part defined in P1.



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

* Re: Indirect visibility of private part in child packages
  2009-06-04  5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne)
@ 2009-06-04  7:50 ` Ludovic Brenta
  2009-06-04 11:47   ` Hibou57 (Yannick Duchêne)
  2009-06-04 16:06 ` Adam Beneschan
  1 sibling, 1 reply; 7+ messages in thread
From: Ludovic Brenta @ 2009-06-04  7:50 UTC (permalink / raw)


Maybe you can solve your problem like this:

package body P1.P3 is
   procedure A_Primitive (Item : out T3_Type) is
   begin
      T1_Type (Item).Low_Level_Data := ...;
   end A_Primitive;
end P1.P3;

I am undecided whether the compiler is correct or wrong about the
visibility of Low_Level_Data. On the one hand, P1.P3 cannot see the
full declaration of T2_Type; on the other hand, it can see that
T2_Type publicly inherits from T1_Type and can also see the full
declaration of T1_Type.

It seems that the public (partial) view of T2_Type hides the full
declaration of T1_Type. So, I think my solution would work by removing
T2_Type out of the way.

Another solution, which enforces encapsulation better, would be:

package P1 is
   type T1_Type is tagged private;
private
   type Some_Type is ...;
   type T1_Type is tagged record
     Low_Level_Data : Some_Type;
   end record;
   procedure Set (Item : out T1_Type; Data : in Some_Type);
end P1;

package body P1.P3 is
   procedure A_Primitive (Item : out T3_Type) is
   begin
      Set (Item, Data => ...); -- OK, calls inherited primitive
operation
   end A_Primitive;
end P1.P3;

HTH

--
Ludovic Brenta.



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

* Re: Indirect visibility of private part in child packages
  2009-06-04  7:50 ` Ludovic Brenta
@ 2009-06-04 11:47   ` Hibou57 (Yannick Duchêne)
  2009-06-04 13:22     ` Robert A Duff
  0 siblings, 1 reply; 7+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-06-04 11:47 UTC (permalink / raw)


Bonjour Ludovic, and thanks for your reply :)

On 4 juin, 09:50, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
> Maybe you can solve your problem like this:
>
> package body P1.P3 is
>    procedure A_Primitive (Item : out T3_Type) is
>    begin
>       T1_Type (Item).Low_Level_Data := ...;
>    end A_Primitive;
> end P1.P3;

I've just tried it, and it does not work better. The compiler
complains there are not selector Low_Level_Data for T1_Type.


> I am undecided whether the compiler is correct or wrong about the
> visibility of Low_Level_Data. On the one hand, P1.P3 cannot see the
> full declaration of T2_Type; on the other hand, it can see that
> T2_Type publicly inherits from T1_Type and can also see the full
> declaration of T1_Type.
This is exactly the same think in my mind. Perhaps the semantic is
ambigous here.

> It seems that the public (partial) view of T2_Type hides the full
> declaration of T1_Type. So, I think my solution would work by removing
> T2_Type out of the way.

T2_Type is required ;) The purpose is to have T2_Type and T3_Type, and
may be later some others, beside of each other.

> Another solution, which enforces encapsulation better, would be:
>
> package P1 is
>    type T1_Type is tagged private;
> private
>    type Some_Type is ...;
>    type T1_Type is tagged record
>      Low_Level_Data : Some_Type;
>    end record;
>    procedure Set (Item : out T1_Type; Data : in Some_Type);
> end P1;
>
> package body P1.P3 is
>    procedure A_Primitive (Item : out T3_Type) is
>    begin
>       Set (Item, Data => ...); -- OK, calls inherited primitive
> operation
>    end A_Primitive;
> end P1.P3;
>
> HTH

I will try it soon and tell about the result. But at first sight, I
think that the compiler gonna complain that Set is a primitive of
T1_Type and thus that it must be defined in the public part. Further
more, I think Set would habe to be redefined for each T2_Type, T3_Type
and etc.

Will try and tell later

Have a nice day



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

* Re: Indirect visibility of private part in child packages
  2009-06-04 11:47   ` Hibou57 (Yannick Duchêne)
@ 2009-06-04 13:22     ` Robert A Duff
  2009-06-04 14:04       ` Hibou57 (Yannick Duchêne)
  0 siblings, 1 reply; 7+ messages in thread
From: Robert A Duff @ 2009-06-04 13:22 UTC (permalink / raw)


"Hibou57 (Yannick Duch�ne)" <yannick_duchene@yahoo.fr> writes:

> On 4 juin, 09:50, Ludovic Brenta <ludo...@ludovic-brenta.org> wrote:
>> Maybe you can solve your problem like this:
>>
>> package body P1.P3 is
>> � �procedure A_Primitive (Item : out T3_Type) is
>> � �begin
>> � � � T1_Type (Item).Low_Level_Data := ...;
>> � �end A_Primitive;
>> end P1.P3;
>
> I've just tried it, and it does not work better. The compiler
> complains there are not selector Low_Level_Data for T1_Type.

Are you sure?  Converting to T1_Type should work.  P3 can see that
T1_Type has a Low_Level_Data component.

The reason your original example didn't work is that the components of
T2_Type are "nailed down" at the point where it's declared,
and P3 can't see that.  It can, however, see that it's derived
from T1_Type, so converting should work.

>> � �procedure Set (Item : out T1_Type; Data : in Some_Type);
>> end P1;
>>
>> package body P1.P3 is
>> � �procedure A_Primitive (Item : out T3_Type) is
>> � �begin
>> � � � Set (Item, Data => ...); -- OK, calls inherited primitive
>> operation
>> � �end A_Primitive;
>> end P1.P3;
>>
>> HTH
>
> I will try it soon and tell about the result. But at first sight, I
> think that the compiler gonna complain that Set is a primitive of
> T1_Type and thus that it must be defined in the public part. Further
> more, I think Set would habe to be redefined for each T2_Type, T3_Type
> and etc.

You could make Set class-wide.

- Bob



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

* Re: Indirect visibility of private part in child packages
  2009-06-04 13:22     ` Robert A Duff
@ 2009-06-04 14:04       ` Hibou57 (Yannick Duchêne)
  0 siblings, 0 replies; 7+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-06-04 14:04 UTC (permalink / raw)


On 4 juin, 15:22, Robert A Duff <bobd...@shell01.TheWorld.com> wrote:
> >> Maybe you can solve your problem like this:
>
> >> package body P1.P3 is
> >>    procedure A_Primitive (Item : out T3_Type) is
> >>    begin
> >>       T1_Type (Item).Low_Level_Data := ...;
> >>    end A_Primitive;
> >> end P1.P3;
>
> > I've just tried it, and it does not work better. The compiler
> > complains there are not selector Low_Level_Data for T1_Type.
>
> Are you sure?  Converting to T1_Type should work.  P3 can see that
> T1_Type has a Low_Level_Data component.

I sware, it is rejected. I agree this is strange.

A GNAT bug ? If it is, perhaps this is the answer to the other
question as well (the question about the visibility).



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

* Re: Indirect visibility of private part in child packages
  2009-06-04  5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne)
  2009-06-04  7:50 ` Ludovic Brenta
@ 2009-06-04 16:06 ` Adam Beneschan
  2009-06-04 16:33   ` Hibou57 (Yannick Duchêne)
  1 sibling, 1 reply; 7+ messages in thread
From: Adam Beneschan @ 2009-06-04 16:06 UTC (permalink / raw)


On Jun 3, 10:45 pm, Hibou57 (Yannick Duchêne)
<yannick_duch...@yahoo.fr> wrote:
> Hi all,
>
> I've meet a tortuous question with a set of packages I'm converting
> from Pascal (as I use Ada now, I'm taking the opportunity to re-create
> a nicer design).
>
> The question I'm facing deals with visibility of private part in child
> package. More precisely, an indirect visibility of a private part. An
> exemple will better show the case:
>
> This can be reduced to three package (specs and bodies)
>
> The root package:
>
> >>>>> --------------------------------------------------
>
> package P1 is
>    type T1_Type is tagged private;
>    -- Some primitives on T1_Type are specified here ...
> private
>    type T1_Type is tagged record
>       Low_Level_Data : Some_Type;
>    end record; -- T1_Type
> end P1;
> <<<<< --------------------------------------------------
>
> The first child package (with this one, every thing's Ok):>>>>> --------------------------------------------------
>
> package P1.P2 is
>    type T2_Type is new T1_Type with private;
>    -- Some primitives on T2_Type are specified here ...
>    procedure A_Primitive (Item : out T2_Type);
> private
>    type T2_Type is new T1_Type with null record;
> end P1.P2;
>
> package body P1.P2 is
>    procedure A_Primitive (Item : out T2_Type) is
>    begin
>       Item.Low_Level_Data := ...;
>       -- It works, beceause P1.P2 is a child
>       -- package with a view on P1's private part
>    end A_Primitive;
> end P1.P2;
> <<<<< --------------------------------------------------
>
> The second child package (the one which turns into a subtile doubt):>>>>> --------------------------------------------------
>
> with P1.P2;
> package P1.P3 is
>    type T3_Type is new P1.P2.T2_Type with private;
>    -- Some primitives on T2_Type are specified here ...
>    procedure A_Primitive (Item : out T3_Type);
> private
>    type T3_Type is new P1.P2.T2_Type with null record;
> end P1.P3;
>
> package body P1.P3 is
>    procedure A_Primitive (Item : out T3_Type) is
>    begin
>       Item.Low_Level_Data := ...;
>       -- It fails : the compiler complains there is no
>       -- selector "Low_Level_Data" defined for T3_Type
>    end A_Primitive;
> end P1.P3;
> <<<<< --------------------------------------------------
>
> As said in the last comment, it seems P1.P3 cannot see the
> T1_Type.Low_Level_Data member. But as P3 is a child package of P1, it
> has a view on P1's private part, and there is indeed no trouble about
> it with P2. P3 know P2.T2_Type is derived from P1.T1_Type, and P3 has
> a view on T1_Type privates. But it seems the compiler does not care
> about it.
>
> There may be interpretation matter here : does the private
> specification, means "disallow access to private part" or does it
> means "do not provide an access to the private part". If it means
> "disallow access to private part", then it ill explain why P3 cannot
> access T1_Type.Low_Level_Data member. But if it means "do no provide
> an access to private" part, then P3 should still be able to access
> T1.Low_Level_Data, beceause it has an access to this as a child
> package of P1.
>
> What does long experienced lawyers think about it ?

Here's why it doesn't work:

The "operation" of providing a selector Low_Level_Data for T1_Type is
made visible in the private part of P1.

When T2_Type is declared as derived from T1_Type, the operation of
providing the selector Low_Level_Data is inherited from T1_Type, but
it only becomes visible where the original operation becomes visible.
Since the original operation is visible in the private part of P1, the
inherited operation becomes visible in the private part of P1.P2,
which is the first place that the private part of P1 is visible.
(It's not relevant that T2_Type is a private extension; I believe it
would work the same if T2_Type were fully declared in the visible
part.)

When T3_Type is declared as derived as T2_Type, the operation of
providing the selector Low_Level_Data is inherited from T2_Type, but
it only becomes visible where the original operation (on T2_Type!!)
becomes visible, which is... nowhere, because there isn't anywhere in
P1.P3 that is able to access P1.P2's private part (and according to
the above paragraph, that's where the operation on T2_Type is made
visible---in P1.P2's private part).  That's why Low_Level_Data isn't
available for T3_Type.

So the compiler is correct to reject your original program.  However,
I think Ludovic's fix (using a type conversion, actually a view
conversion) should work, and it's a compiler bug if that is rejected.

One could argue that this rule is anomalous, and that if a type is
visibly derived from a grandparent (or great-grandparent, etc.) type
in a situation like this, then operations that are indirectly
inherited from the grandparent (etc.) type should be visible if
they're visible for the grandparent, even if the inheritance comes
indirectly through a non-visible part of some other package.  There
could be a privacy problem if the operation could be overridden in the
non-visible part, but that isn't possible here---there's nothing P1.P2
can do to change the meaning of the Low_Level_Data selector.  This
issue is related to AI05-125, but although a couple of us think
there's a flaw in the language, others believe that it can't be fixed
without making things even more confusing.  In any event, it's not all
that important here since the view conversion is an adequate
workaround, assuming your compiler isn't broken.


> I've try to look in section 8 of the "RM 2005", but either the answer
> was not there or else, I missed it.

I think 7.3.1 and particularly 7.3.1(4) is the important rule here,
although I have to admit that that section uses a lot of slightly
fuzzy generalities that I've had problems interpreting occasionally.

                                    -- Adam




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

* Re: Indirect visibility of private part in child packages
  2009-06-04 16:06 ` Adam Beneschan
@ 2009-06-04 16:33   ` Hibou57 (Yannick Duchêne)
  0 siblings, 0 replies; 7+ messages in thread
From: Hibou57 (Yannick Duchêne) @ 2009-06-04 16:33 UTC (permalink / raw)


On 4 juin, 18:06, Adam Beneschan <a...@irvine.com> wrote:
> So the compiler is correct to reject your original program.  However,
> I think Ludovic's fix (using a type conversion, actually a view
> conversion) should work, and it's a compiler bug if that is rejected.

I've done an error in my prior : T1_Type(Item).Low_Level_Data finally
works fine.

By the way, thanks for this clean explanation (and I gonna have a
further look at 7.3x)



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

end of thread, other threads:[~2009-06-04 16:33 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-06-04  5:45 Indirect visibility of private part in child packages Hibou57 (Yannick Duchêne)
2009-06-04  7:50 ` Ludovic Brenta
2009-06-04 11:47   ` Hibou57 (Yannick Duchêne)
2009-06-04 13:22     ` Robert A Duff
2009-06-04 14:04       ` Hibou57 (Yannick Duchêne)
2009-06-04 16:06 ` Adam Beneschan
2009-06-04 16:33   ` Hibou57 (Yannick Duchêne)

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