comp.lang.ada
 help / color / mirror / Atom feed
* Indefinite Containers of Indefinite Private Types
@ 2015-08-04  2:23 Jeffrey R. Carter
  2015-08-04  5:40 ` Niklas Holsti
  0 siblings, 1 reply; 10+ messages in thread
From: Jeffrey R. Carter @ 2015-08-04  2:23 UTC (permalink / raw)


This is legal:

package Indefinite1 is
   type T (<>) is private;
private -- Indefinite1
   type T is new String;
end Indefinite1;

with Indefinite1;
with Ada.Containers.Indefinite_Vectors;

package Indefinite2 is
   use type Indefinite1.T;

   package Lists is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => Indefinite1.T);
end Indefinite2;

But this isn't:

with Ada.Containers.Indefinite_Vectors;

package Indefinite1 is
   type T (<>) is private;
private -- Indefinite1
   package Lists is new Ada.Containers.Indefinite_Vectors
      (Index_Type => Positive, Element_Type => T);

   type T is new String;
end Indefinite1;

It seems to me that both instantiations have all the information they need.
Probably I'm missing something, but why is the latter illegal?

-- 
Jeff Carter
"English bed-wetting types."
Monty Python & the Holy Grail
15


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04  2:23 Indefinite Containers of Indefinite Private Types Jeffrey R. Carter
@ 2015-08-04  5:40 ` Niklas Holsti
  2015-08-04 18:56   ` Jeffrey R. Carter
  0 siblings, 1 reply; 10+ messages in thread
From: Niklas Holsti @ 2015-08-04  5:40 UTC (permalink / raw)


On 15-08-04 05:23 , Jeffrey R. Carter wrote:
> This is legal:
>
> package Indefinite1 is
>     type T (<>) is private;
> private -- Indefinite1
>     type T is new String;
> end Indefinite1;
>
> with Indefinite1;
> with Ada.Containers.Indefinite_Vectors;
>
> package Indefinite2 is
>     use type Indefinite1.T;
>
>     package Lists is new Ada.Containers.Indefinite_Vectors
>        (Index_Type => Positive, Element_Type => Indefinite1.T);
> end Indefinite2;
>
> But this isn't:
>
> with Ada.Containers.Indefinite_Vectors;
>
> package Indefinite1 is
>     type T (<>) is private;
> private -- Indefinite1
>     package Lists is new Ada.Containers.Indefinite_Vectors
>        (Index_Type => Positive, Element_Type => T);
>
>     type T is new String;
> end Indefinite1;
>
> It seems to me that both instantiations have all the information they need.
> Probably I'm missing something, but why is the latter illegal?

I'm not sure that I have understood your question correctly -- are you 
asking for the RM rule that makes this illegal, or for the reason behind 
that rule?

At the point of instantiation in the second case, "T" is a partial view 
of the type. RM 7.3(5) says "... Similarly, before the full declaration, 
the name of the partial view cannot be used in a generic_instantiation 
or in a representation item."

As to why this rule exists, I suspect it has to do with the "rechecks" 
discussed in the annotated RM 12.3(11) where the legality of an 
instantiation is checked by comparing the actual types with the _full_ 
declaration of the generic (not only with the declarations of the 
generic formals). It might be difficult to apply these rechecks if the 
actual type is only a partial view.

The second case becomes legal if the full declaration of type T is moved 
to occur before the instantiation -- as happens in the first case -- but 
you probably knew that.

-- 
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
       .      @       .


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04  5:40 ` Niklas Holsti
@ 2015-08-04 18:56   ` Jeffrey R. Carter
  2015-08-04 20:47     ` Randy Brukardt
  2015-08-07 20:13     ` Bob Duff
  0 siblings, 2 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2015-08-04 18:56 UTC (permalink / raw)


On 08/03/2015 10:40 PM, Niklas Holsti wrote:
> 
> I'm not sure that I have understood your question correctly -- are you asking
> for the RM rule that makes this illegal, or for the reason behind that rule?

Sorry if I was unclear. I know the ARM prohibits using an uncompleted private
type as the actual for a generic formal. I'm wondering why this applies to the
case of a generic formal indefinite private type.

Reading that leads me to think that I should have used a subject referring to
generic formal indefinite private types rather than indefinite containers.

> At the point of instantiation in the second case, "T" is a partial view of the
> type. RM 7.3(5) says "... Similarly, before the full declaration, the name of
> the partial view cannot be used in a generic_instantiation or in a
> representation item."

Right. This rule has the advantage of being simple. It seems to me it may have
the disadvantage of disallowing feasible instantiations.

> As to why this rule exists, I suspect it has to do with the "rechecks" discussed
> in the annotated RM 12.3(11) where the legality of an instantiation is checked
> by comparing the actual types with the _full_ declaration of the generic (not
> only with the declarations of the generic formals). It might be difficult to
> apply these rechecks if the actual type is only a partial view.

What a generic can do with a formal indefinite private type is quite limited.
Nothing it can do seems to me to need to know the full type definition. Maybe
I've overlooked something, or maybe there's a good reason why something I don't
think needs the full definition actually does. I'm curious whether such
instantiations could be legal, and what I missed if they can't.

> The second case becomes legal if the full declaration of type T is moved to
> occur before the instantiation -- as happens in the first case -- but you
> probably knew that.

Yes, of course. The examples are simplified from a more complex case where the
container is used in the full type definition. This can be achieved by adding
some additional code that is essentially noise, or by using access types.
Avoiding access types is worth adding noise, but it would be nice if the noise
were unnecessary.

-- 
Jeff Carter
"Have you gone berserk? Can't you see that that man is a ni?"
Blazing Saddles
38


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04 18:56   ` Jeffrey R. Carter
@ 2015-08-04 20:47     ` Randy Brukardt
  2015-08-04 20:56       ` Jeffrey R. Carter
  2015-08-07 20:13     ` Bob Duff
  1 sibling, 1 reply; 10+ messages in thread
From: Randy Brukardt @ 2015-08-04 20:47 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:mpr1po$4sn$1@dont-email.me...
> On 08/03/2015 10:40 PM, Niklas Holsti wrote:
>>
>> I'm not sure that I have understood your question correctly -- are you 
>> asking
>> for the RM rule that makes this illegal, or for the reason behind that 
>> rule?
>
> Sorry if I was unclear. I know the ARM prohibits using an uncompleted 
> private
> type as the actual for a generic formal. I'm wondering why this applies to 
> the
> case of a generic formal indefinite private type.

An amazing amount of ARG hair has been pulled over this issue. There are 
about 10 AIs on the topic, none of which have gotten particularly close to 
being accepted.

The very short answer is that an object can be created of such a type, so it 
doesn't help that the type is indefinite (the problems with allowing this 
tend to be in freezing and elaboration rules, particularly in not changing 
the rules incompatibly).

Specifically:

    generic
       type T (<>) is private;
       function Creator return T;
    package G is
       Obj : T := Creator; -- Legal.
    end G;

Note that such an object would be illegal before the full completion of the 
private type. So, if you put that object declaration into the body, you have 
a contract model violation. Therein is the problem.

One could imagine having a declaration for the generic (perhaps an aspect?) 
that would allow such instantiations (and disallow such objects), but again 
there has been little traction for such proposals, all of which are quite 
complex to describe and implement.

...
>> At the point of instantiation in the second case, "T" is a partial view 
>> of the
>> type. RM 7.3(5) says "... Similarly, before the full declaration, the 
>> name of
>> the partial view cannot be used in a generic_instantiation or in a
>> representation item."
>
> Right. This rule has the advantage of being simple. It seems to me it may 
> have
> the disadvantage of disallowing feasible instantiations.

Sure, but there can't be any objects in the generic. Even if there isn't a 
constructor function, any parameter of type T could have been used in "new".

>> I suppose this to do with the "rechecks" discussed
>> in the annotated RM 12.3(11) where the legality of an instantiation is 
>> checked
>> by comparing the actual types with the _full_ declaration of the generic 
>> (not
>> only with the declarations of the generic formals). It might be difficult 
>> to
>> apply these rechecks if the actual type is only a partial view.
>
> What a generic can do with a formal indefinite private type is quite 
> limited.
> Nothing it can do seems to me to need to know the full type definition. 
> Maybe
> I've overlooked something, or maybe there's a good reason why something I 
> don't
> think needs the full definition actually does. I'm curious whether such
> instantiations could be legal, and what I missed if they can't.

Declaring an object surely needs the full declaration, and I showed above 
how to do it. Recall that the elaboration of the body occurs at the point of 
the instance (before the full declaration of the private type).

One can make signature packages with formal incomplete types (which can be 
instantiated with private types before the completion), but it's hard to 
make a useful container that way. (It's not impossible, but you have to use 
more access types than I find comfortable.)

>> The second case becomes legal if the full declaration of type T is moved 
>> to
>> occur before the instantiation -- as happens in the first case -- but you
>> probably knew that.
>
> Yes, of course. The examples are simplified from a more complex case where 
> the
> container is used in the full type definition. This can be achieved by 
> adding
> some additional code that is essentially noise, or by using access types.
> Avoiding access types is worth adding noise, but it would be nice if the 
> noise
> were unnecessary.

I agree, but the ARG has not been able to find an acceptable solution to 
this problem. And we surely have tried:

AI95-00359-01, AI95-00359-02, AI95-00359-03, AI95-00359-04, AI05-0074-1, 
AI05-0074-2, AI05-0074-3, AI05-0074-4, AI05-0074-5 (AI05-0011-1 was also 
related, but it was a duplicate).

We're pretty much pooped out on this topic. Sometimes there just is no 
answer that can get a consensus.

                                   Randy. 




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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04 20:47     ` Randy Brukardt
@ 2015-08-04 20:56       ` Jeffrey R. Carter
  2015-08-06 18:49         ` Randy Brukardt
  0 siblings, 1 reply; 10+ messages in thread
From: Jeffrey R. Carter @ 2015-08-04 20:56 UTC (permalink / raw)


On 08/04/2015 01:47 PM, Randy Brukardt wrote:
> 
> An amazing amount of ARG hair has been pulled over this issue. There are 
> about 10 AIs on the topic, none of which have gotten particularly close to 
> being accepted.
> 
> The very short answer is that an object can be created of such a type, so it 
> doesn't help that the type is indefinite (the problems with allowing this 
> tend to be in freezing and elaboration rules, particularly in not changing 
> the rules incompatibly).
> 
> Specifically:
> 
>     generic
>        type T (<>) is private;
>        function Creator return T;
>     package G is
>        Obj : T := Creator; -- Legal.
>     end G;
> 
> Note that such an object would be illegal before the full completion of the 
> private type. So, if you put that object declaration into the body, you have 
> a contract model violation. Therein is the problem.

Of course. I guess I was thinking too much in terms of what a container does
with the type and not in general.

> One could imagine having a declaration for the generic (perhaps an aspect?) 
> that would allow such instantiations (and disallow such objects), but again 
> there has been little traction for such proposals, all of which are quite 
> complex to describe and implement.

I can guess so. Probably a new generic formal type would be desired. Meanwhile
I'll put up with the noise.

-- 
Jeff Carter
"Have you gone berserk? Can't you see that that man is a ni?"
Blazing Saddles
38


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04 20:56       ` Jeffrey R. Carter
@ 2015-08-06 18:49         ` Randy Brukardt
  2015-08-06 20:12           ` Jeffrey R. Carter
  0 siblings, 1 reply; 10+ messages in thread
From: Randy Brukardt @ 2015-08-06 18:49 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:mpr8rn$33n$1@dont-email.me...
> On 08/04/2015 01:47 PM, Randy Brukardt wrote:
...
>> One could imagine having a declaration for the generic (perhaps an 
>> aspect?)
>> that would allow such instantiations (and disallow such objects), but 
>> again
>> there has been little traction for such proposals, all of which are quite
>> complex to describe and implement.
>
> I can guess so. Probably a new generic formal type would be desired. 
> Meanwhile
> I'll put up with the noise.

That's one possibility. We could call it a generic private type. Oops --  
that name is taken, and alternative names are annoying. (The idea of course 
would be similar to the generic incomplete type; the restrictions on the use 
of a private type would be enforced on the uses of the generic formal type.)

We've also looked at declarations (maybe an aspect) for the generic as a 
whole, there was a proposal for a "forward" declaration for the generic 
(that is, you'd be able to separate the visible part of the generic from the 
actual instance, just like in other kinds of packages), and a proposal to 
change the freezing to be exactly like a macro (meaning a break in the 
contract model, and a horror to implement on top of that). We also found 
that there is a workaround of sorts using a child package to hold the 
instantiation, which works so long as the private type doesn't use something 
from the instantiation (usually a cursor for a container) in its full 
declaration. The existence of the workaround lowers the priority of finding 
a fix, and given the difficulty of doing so, we pretty much gave up. I'm 
sure we'll revisit it someday.

                                                     Randy.


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-06 18:49         ` Randy Brukardt
@ 2015-08-06 20:12           ` Jeffrey R. Carter
  2015-08-07 19:49             ` Randy Brukardt
  0 siblings, 1 reply; 10+ messages in thread
From: Jeffrey R. Carter @ 2015-08-06 20:12 UTC (permalink / raw)


On 08/06/2015 11:49 AM, Randy Brukardt wrote:
> 
> That's one possibility. We could call it a generic private type. Oops --  
> that name is taken, and alternative names are annoying. (The idea of course 
> would be similar to the generic incomplete type; the restrictions on the use 
> of a private type would be enforced on the uses of the generic formal type.)
> 
> We've also looked at declarations (maybe an aspect) for the generic as a 
> whole, there was a proposal for a "forward" declaration for the generic 
> (that is, you'd be able to separate the visible part of the generic from the 
> actual instance, just like in other kinds of packages), and a proposal to 
> change the freezing to be exactly like a macro (meaning a break in the 
> contract model, and a horror to implement on top of that). We also found 
> that there is a workaround of sorts using a child package to hold the 
> instantiation, which works so long as the private type doesn't use something 
> from the instantiation (usually a cursor for a container) in its full 
> declaration. The existence of the workaround lowers the priority of finding 
> a fix, and given the difficulty of doing so, we pretty much gave up. I'm 
> sure we'll revisit it someday.

I looked at some of the AIs you mentioned and saw there were a number of ideas.
The child-pkg workaround involves using an access type, so it doesn't seem to
gain anything over using access types directly, and is less attractive than
access-free noise, which seems to me to be another work around not considered in
the discussion I looked at.

The problem seems to be that there is a single instantiation for both the spec
and body, and the body occurs and is elaborated immediately at the point of the
instantiation. Another language might instantiate the spec and body separately,
allowing the body to be instantiated after the full type. There were some
suggestions in the AIs along that line, but couched in terms of delaying
freezing rather than separation of spec and body.

Maybe something like

package P is
   type T (<>) is private;
private
   package Lists is new Indefinite_Vectors
      (Index_Type => Positive, Element_Type => T)
   with not body;

   type T is record
      List : Lists.Vector;
   end record;
end P;

package body P is
   package body Lists is new Indefinite_Vectors;
   ...

I guess I'm beating a dead hippopotamus here.

-- 
Jeff Carter
"Facts do not cease to exist because they are ignored."
Aldous Huxley
134


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-06 20:12           ` Jeffrey R. Carter
@ 2015-08-07 19:49             ` Randy Brukardt
  0 siblings, 0 replies; 10+ messages in thread
From: Randy Brukardt @ 2015-08-07 19:49 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> wrote in message 
news:mq0f0g$7im$1@dont-email.me...
> On 08/06/2015 11:49 AM, Randy Brukardt wrote:
>>
>> That's one possibility. We could call it a generic private type. Oops --
>> that name is taken, and alternative names are annoying. (The idea of 
>> course
>> would be similar to the generic incomplete type; the restrictions on the 
>> use
>> of a private type would be enforced on the uses of the generic formal 
>> type.)
>>
>> We've also looked at declarations (maybe an aspect) for the generic as a
>> whole, there was a proposal for a "forward" declaration for the generic
>> (that is, you'd be able to separate the visible part of the generic from 
>> the
>> actual instance, just like in other kinds of packages), and a proposal to
>> change the freezing to be exactly like a macro (meaning a break in the
>> contract model, and a horror to implement on top of that). We also found
>> that there is a workaround of sorts using a child package to hold the
>> instantiation, which works so long as the private type doesn't use 
>> something
>> from the instantiation (usually a cursor for a container) in its full
>> declaration. The existence of the workaround lowers the priority of 
>> finding
>> a fix, and given the difficulty of doing so, we pretty much gave up. I'm
>> sure we'll revisit it someday.
>
> I looked at some of the AIs you mentioned and saw there were a number of 
> ideas.
> The child-pkg workaround involves using an access type, so it doesn't seem 
> to
> gain anything over using access types directly, and is less attractive 
> than
> access-free noise, which seems to me to be another work around not 
> considered in
> the discussion I looked at.
>
> The problem seems to be that there is a single instantiation for both the 
> spec
> and body, and the body occurs and is elaborated immediately at the point 
> of the
> instantiation. Another language might instantiate the spec and body 
> separately,
> allowing the body to be instantiated after the full type. There were some
> suggestions in the AIs along that line, but couched in terms of delaying
> freezing rather than separation of spec and body.
>
> Maybe something like
>
> package P is
>   type T (<>) is private;
> private
>   package Lists is new Indefinite_Vectors
>      (Index_Type => Positive, Element_Type => T)
>   with not body;
>
>   type T is record
>      List : Lists.Vector;
>   end record;
> end P;
>
> package body P is
>   package body Lists is new Indefinite_Vectors;
>   ...

I had suggested something along this line (not exactly this, though), but at 
least some people were trying to do this without making any work for the 
client. But of course that causes incompatibilties; which led to arguments 
about how important the incompatibilities are, and that tends to lead 
nowhere.

> I guess I'm beating a dead hippopotamus here.

Yup.

                             Randy.


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-04 18:56   ` Jeffrey R. Carter
  2015-08-04 20:47     ` Randy Brukardt
@ 2015-08-07 20:13     ` Bob Duff
  2015-08-07 20:45       ` Jeffrey R. Carter
  1 sibling, 1 reply; 10+ messages in thread
From: Bob Duff @ 2015-08-07 20:13 UTC (permalink / raw)


"Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:

> Yes, of course. The examples are simplified from a more complex case where the
> container is used in the full type definition. This can be achieved by adding
> some additional code that is essentially noise, or by using access types.
> Avoiding access types is worth adding noise, but it would be nice if the noise
> were unnecessary.

I'm curious what the "noise" looks like in your case.

Last time I ran into this problem I think I ended up using a workaround
that involved access types.  I don't remember the details.

- Bob


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

* Re: Indefinite Containers of Indefinite Private Types
  2015-08-07 20:13     ` Bob Duff
@ 2015-08-07 20:45       ` Jeffrey R. Carter
  0 siblings, 0 replies; 10+ messages in thread
From: Jeffrey R. Carter @ 2015-08-07 20:45 UTC (permalink / raw)


On 08/07/2015 01:13 PM, Bob Duff wrote:
> "Jeffrey R. Carter" <spam.jrcarter.not@spam.not.acm.org> writes:
> 
>> Yes, of course. The examples are simplified from a more complex case where the
>> container is used in the full type definition. This can be achieved by adding
>> some additional code that is essentially noise, or by using access types.
>> Avoiding access types is worth adding noise, but it would be nice if the noise
>> were unnecessary.
> 
> I'm curious what the "noise" looks like in your case.
> 
> Last time I ran into this problem I think I ended up using a workaround
> that involved access types.  I don't remember the details.

It involves using tagged types, type extension, and a container of a class-wide
type:

with Ada.Containers.Indefinite_Vectors;

package P is
   type T (<>) is private;
private
   type Root is tagged null record;

   package Lists is new Ada.Containers.Vectors
      (Index_Type => Positive, Element_Type => Root'Class);

   type T is new Root with record
      List : Lists.Vector;
   end T;
end P;

The only reason for the type extension is to get the instantiation that can be
used in the full declaration of T. The only objects that will be stored in a
vector are of type T. In addition to the noise of the Root type and the
extension for T, there are type conversions required that are part of the noise.

-- 
Jeff Carter
"From this day on, the official language of San Marcos will be Swedish."
Bananas
28


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

end of thread, other threads:[~2015-08-07 20:45 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-04  2:23 Indefinite Containers of Indefinite Private Types Jeffrey R. Carter
2015-08-04  5:40 ` Niklas Holsti
2015-08-04 18:56   ` Jeffrey R. Carter
2015-08-04 20:47     ` Randy Brukardt
2015-08-04 20:56       ` Jeffrey R. Carter
2015-08-06 18:49         ` Randy Brukardt
2015-08-06 20:12           ` Jeffrey R. Carter
2015-08-07 19:49             ` Randy Brukardt
2015-08-07 20:13     ` Bob Duff
2015-08-07 20:45       ` Jeffrey R. Carter

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