comp.lang.ada
 help / color / mirror / Atom feed
* Rationale for this not to compile?
@ 2014-07-24 20:53 Victor Porton
  2014-07-24 21:36 ` Adam Beneschan
  2014-07-25 13:18 ` Victor Porton
  0 siblings, 2 replies; 9+ messages in thread
From: Victor Porton @ 2014-07-24 20:53 UTC (permalink / raw)


Is there any rationale why this does not compile? If it compiled, it would 
be probably useful in practice with a real example similar to the below toy 
example (as to make the type T not private, I must create an *.Internal.* 
package to serve as a "private repository" for types like T, as real private 
types cannot be used). It is called a hack.

gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr test.ads
test.ads:10:32: premature use of private type
gnatmake: "/home/porton/t/test.ads" compilation error

package Test is

   generic
      type T is limited private;
   package Gen is
   end Gen;
   
   type X is private;

   package Instance is new Gen(X);
   
private
   
   type X is null record;
   
end Test;

-- 
Victor Porton - http://portonvictor.org


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

* Re: Rationale for this not to compile?
  2014-07-24 20:53 Rationale for this not to compile? Victor Porton
@ 2014-07-24 21:36 ` Adam Beneschan
  2014-07-25  5:29   ` Randy Brukardt
  2014-07-25 13:18 ` Victor Porton
  1 sibling, 1 reply; 9+ messages in thread
From: Adam Beneschan @ 2014-07-24 21:36 UTC (permalink / raw)


On Thursday, July 24, 2014 1:53:32 PM UTC-7, Victor Porton wrote:
> Is there any rationale why this does not compile? 

A generic instantiation is equivalent to "the instance declaration ... immediately followed by the instance body, both at the place of the instantiation."  (12.3(12)) Since the body could contain code that depends on the representation of X already being determined, but it hasn't yet, the language makes this illegal.  At least I think that's the rationale.  AARM section 13.14, which discusses the freezing rules, explains in more detail why types have to be completely defined before they're used in certain cases (see http://www.ada-auth.org/standards/12aarm/html/AA-13-14.html).

                             -- Adam



> If it compiled, it would 
> be probably useful in practice with a real example similar to the below toy 
> example (as to make the type T not private, I must create an *.Internal.* 
> package to serve as a "private repository" for types like T, as real private 
> types cannot be used). It is called a hack.
> 
> gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr test.ads
> test.ads:10:32: premature use of private type
> gnatmake: "/home/porton/t/test.ads" compilation error
> 
> package Test is
> 
>    generic
>       type T is limited private;
>    package Gen is
>    end Gen;
> 
>    type X is private;
> 
>    package Instance is new Gen(X);
> 
> private
>    type X is null record;
> end Test;


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

* Re: Rationale for this not to compile?
  2014-07-24 21:36 ` Adam Beneschan
@ 2014-07-25  5:29   ` Randy Brukardt
  2014-07-25 12:19     ` Victor Porton
  2014-07-25 14:40     ` Robert A Duff
  0 siblings, 2 replies; 9+ messages in thread
From: Randy Brukardt @ 2014-07-25  5:29 UTC (permalink / raw)



"Adam Beneschan" <adambeneschan@gmail.com> wrote in message 
news:1cb91e6a-9e49-4bc8-bf4a-67a16a00e3a0@googlegroups.com...
>On Thursday, July 24, 2014 1:53:32 PM UTC-7, Victor Porton wrote:
>> Is there any rationale why this does not compile?
>
>A generic instantiation is equivalent to "the instance declaration ... 
>immediately followed
>by the instance body, both at the place of the instantiation."  (12.3(12)) 
>Since the body
>could contain code that depends on the representation of X already being 
>determined,
>but it hasn't yet, the language makes this illegal.  At least I think 
>that's the rationale.
>AARM section 13.14, which discusses the freezing rules, explains in more 
>detail why
>types have to be completely defined before they're used in certain cases 
>(see
> http://www.ada-auth.org/standards/12aarm/html/AA-13-14.html).

That's a pretty good explanation.

We (the ARG) have spent dozens of hours attempting to find a way to allow 
something like the OPs example. (There's something like 10 AIs associated 
with that.) Each solution had some sort of fatal flaw (implementability, 
maintenance problems, too hard to use, etc.)

The best solution is the put the instance into a child package; one of the 
reasons that we didn't adopt any of the ugly solutions is that using a child 
package often works fine and an ugly solution doesn't seem worth it in that 
case.

In the special case where the generic has little implementation of it's own 
(a signature package), one can use a formal incomplete type as the formal 
type; it does allow an instantiation like the one the OP wrote. 
Specifically:

package OK_Test is

   generic
      type T;
   package Gen is
   end Gen;

   type X is private;

   package Instance is new Gen(X);

private

   type X is null record;

end OK_Test;

is legal. But the use of the formal incomplete type strongly restricts what 
you can do in the generic unit (because it's an incomplete type, and those 
allow very limited uses).

One of my pet projects (that I don't have any time to follow up on!) is to 
create a useful container where the element type is a formal incomplete 
type. I think that the container would have to manage elements that live 
elsewhere (unlike Ada.Containers) -- since element creation isn't possible, 
but this would allow a container of limited elements, and of course would 
allow instantiation by a private type as here.

                                          Randy.






> If it compiled, it would
> be probably useful in practice with a real example similar to the below 
> toy
> example (as to make the type T not private, I must create an *.Internal.*
> package to serve as a "private repository" for types like T, as real 
> private
> types cannot be used). It is called a hack.
>
> gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr test.ads
> test.ads:10:32: premature use of private type
> gnatmake: "/home/porton/t/test.ads" compilation error
>
> package Test is
>
>    generic
>       type T is limited private;
>    package Gen is
>    end Gen;
>
>    type X is private;
>
>    package Instance is new Gen(X);
>
> private
>    type X is null record;
> end Test; 




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

* Re: Rationale for this not to compile?
  2014-07-25  5:29   ` Randy Brukardt
@ 2014-07-25 12:19     ` Victor Porton
  2014-07-25 12:35       ` AdaMagica
  2014-07-25 14:40     ` Robert A Duff
  1 sibling, 1 reply; 9+ messages in thread
From: Victor Porton @ 2014-07-25 12:19 UTC (permalink / raw)


Randy Brukardt wrote:

> 
> "Adam Beneschan" <adambeneschan@gmail.com> wrote in message
> news:1cb91e6a-9e49-4bc8-bf4a-67a16a00e3a0@googlegroups.com...
>>On Thursday, July 24, 2014 1:53:32 PM UTC-7, Victor Porton wrote:
>>> Is there any rationale why this does not compile?
>>
>>A generic instantiation is equivalent to "the instance declaration ...
>>immediately followed
>>by the instance body, both at the place of the instantiation."  (12.3(12))
>>Since the body
>>could contain code that depends on the representation of X already being
>>determined,
>>but it hasn't yet, the language makes this illegal.  At least I think
>>that's the rationale.
>>AARM section 13.14, which discusses the freezing rules, explains in more
>>detail why
>>types have to be completely defined before they're used in certain cases
>>(see
>> http://www.ada-auth.org/standards/12aarm/html/AA-13-14.html).
> 
> That's a pretty good explanation.
> 
> We (the ARG) have spent dozens of hours attempting to find a way to allow
> something like the OPs example. (There's something like 10 AIs associated
> with that.) Each solution had some sort of fatal flaw (implementability,
> maintenance problems, too hard to use, etc.)
> 
> The best solution is the put the instance into a child package; one of the
> reasons that we didn't adopt any of the ugly solutions is that using a
> child package often works fine and an ugly solution doesn't seem worth it
> in that case.
> 
> In the special case where the generic has little implementation of it's
> own (a signature package), one can use a formal incomplete type as the
> formal type; it does allow an instantiation like the one the OP wrote.
> Specifically:
> 
> package OK_Test is
> 
>    generic
>       type T;
>    package Gen is
>    end Gen;
> 
>    type X is private;
> 
>    package Instance is new Gen(X);
> 
> private
> 
>    type X is null record;
> 
> end OK_Test;
> 
> is legal. But the use of the formal incomplete type strongly restricts
> what you can do in the generic unit (because it's an incomplete type, and
> those allow very limited uses).
> 
> One of my pet projects (that I don't have any time to follow up on!) is to
> create a useful container where the element type is a formal incomplete
> type. I think that the container would have to manage elements that live
> elsewhere (unlike Ada.Containers) -- since element creation isn't
> possible, but this would allow a container of limited elements, and of
> course would allow instantiation by a private type as here.
> 
>                                           Randy.
> 
> 
> 
> 
> 
> 
>> If it compiled, it would
>> be probably useful in practice with a real example similar to the below
>> toy
>> example (as to make the type T not private, I must create an *.Internal.*
>> package to serve as a "private repository" for types like T, as real
>> private
>> types cannot be used). It is called a hack.
>>
>> gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr test.ads
>> test.ads:10:32: premature use of private type
>> gnatmake: "/home/porton/t/test.ads" compilation error
>>
>> package Test is
>>
>>    generic
>>       type T is limited private;
>>    package Gen is
>>    end Gen;
>>
>>    type X is private;
>>
>>    package Instance is new Gen(X);
>>
>> private
>>    type X is null record;
>> end Test;

Sorry for a stupid question:

What is the difference of:

generic
    type T
package Gen is
end Gen;

and

generic
    type T is private
package Gen is
end Gen;


-- 
Victor Porton - http://portonvictor.org


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

* Re: Rationale for this not to compile?
  2014-07-25 12:19     ` Victor Porton
@ 2014-07-25 12:35       ` AdaMagica
  0 siblings, 0 replies; 9+ messages in thread
From: AdaMagica @ 2014-07-25 12:35 UTC (permalink / raw)


generic
  type T;  -- an incomplete type
package Gen is
end Gen;

An incomplete type is - ahem - incomplete, the compiler does not and cannot know anything about it. It must later be completed somewhere in the code. Thus very little can be done in the body of the generic with an incomplete type (e.g. no assignment).

It's like
  type T;
  type T_Ptr is access T;
  type T is ...

generic
  type T is private;  -- a private type
package Gen is
end Gen;

The compiler may make assumptions about the type, e.g. object declaration and assignment are possible.


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

* Re: Rationale for this not to compile?
  2014-07-24 20:53 Rationale for this not to compile? Victor Porton
  2014-07-24 21:36 ` Adam Beneschan
@ 2014-07-25 13:18 ` Victor Porton
  1 sibling, 0 replies; 9+ messages in thread
From: Victor Porton @ 2014-07-25 13:18 UTC (permalink / raw)


Victor Porton wrote:

> Is there any rationale why this does not compile? If it compiled, it would
> be probably useful in practice with a real example similar to the below
> toy example (as to make the type T not private, I must create an
> *.Internal.* package to serve as a "private repository" for types like T,
> as real private types cannot be used). It is called a hack.
> 
> gnatmake -q -c -gnatc -u -P/home/porton/t/default.gpr test.ads
> test.ads:10:32: premature use of private type
> gnatmake: "/home/porton/t/test.ads" compilation error
> 
> package Test is
> 
>    generic
>       type T is limited private;
>    package Gen is
>    end Gen;
>    
>    type X is private;
> 
>    package Instance is new Gen(X);
>    
> private
>    
>    type X is null record;
>    
> end Test;

My specific problem was solved replacing

   generic
      type T is limited private;

with

   generic
      type T;

-- 
Victor Porton - http://portonvictor.org

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

* Re: Rationale for this not to compile?
  2014-07-25  5:29   ` Randy Brukardt
  2014-07-25 12:19     ` Victor Porton
@ 2014-07-25 14:40     ` Robert A Duff
  2014-07-25 19:45       ` Randy Brukardt
  1 sibling, 1 reply; 9+ messages in thread
From: Robert A Duff @ 2014-07-25 14:40 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> One of my pet projects (that I don't have any time to follow up on!) is to 
> create a useful container where the element type is a formal incomplete 
> type. I think that the container would have to manage elements that live 
> elsewhere (unlike Ada.Containers) -- since element creation isn't possible, 
> but this would allow a container of limited elements, and of course would 
> allow instantiation by a private type as here.

Sounds interesting, but I don't understand what you mean by "live
elsewhere".  Could you outline how this would work?  I'm having trouble
seeing what use is a "container" that doesn't contain any elements.

- Bob


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

* Re: Rationale for this not to compile?
  2014-07-25 14:40     ` Robert A Duff
@ 2014-07-25 19:45       ` Randy Brukardt
  2014-07-25 20:33         ` Robert A Duff
  0 siblings, 1 reply; 9+ messages in thread
From: Randy Brukardt @ 2014-07-25 19:45 UTC (permalink / raw)


"Robert A Duff" <bobduff@shell01.TheWorld.com> wrote in message 
news:wccvbql5won.fsf@shell01.TheWorld.com...
> "Randy Brukardt" <randy@rrsoftware.com> writes:
>
>> One of my pet projects (that I don't have any time to follow up on!) is 
>> to
>> create a useful container where the element type is a formal incomplete
>> type. I think that the container would have to manage elements that live
>> elsewhere (unlike Ada.Containers) -- since element creation isn't 
>> possible,
>> but this would allow a container of limited elements, and of course would
>> allow instantiation by a private type as here.
>
> Sounds interesting, but I don't understand what you mean by "live
> elsewhere".  Could you outline how this would work?  I'm having trouble
> seeing what use is a "container" that doesn't contain any elements.

I left out one part: the elements would have to be tagged, because "tagged 
incomplete" allows a number of things that regular incomplete doesn't. (In 
particular, they're assumed to be passed by-reference, so parameters are 
allowed). Access after insertion would be via Reference/Constant_Reference 
only (can't make a copy of the element, obviously, and no functions can 
return the element).

Anyway, you can't create an object of an incomplete type, so the client has 
to do that before adding it to the container. That means the container's job 
is to manage the relationships between the elements (and the lookup 
mechanism, for maps and sets).

For instance, one could have a bunch of tasks, and put them into a map 
container in order to add a lookup mechanism to them. Something like:

     Tasks : array (1 .. 10) of My_Task; -- Assume My_Task is tagged.
     package My_Task_Map is new Randys_Super_Duper_Map_Container (String, 
My_Task);
     My_Map : My_Task_Map.Map;
     ...
     My_Map.Insert ("Bob", Tasks(1));
     My_Map.Insert ("Randy", Tasks(2));
     My_Map.Insert ("Tucker", Tasks(3));
     My_Map.Insert ("Steve", Tasks(4));

    --
    My_Map("Bob").My_Entry (...); -- Entry call on the task associated with 
"Bob".

Does this make sense?

                                Randy.

 




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

* Re: Rationale for this not to compile?
  2014-07-25 19:45       ` Randy Brukardt
@ 2014-07-25 20:33         ` Robert A Duff
  0 siblings, 0 replies; 9+ messages in thread
From: Robert A Duff @ 2014-07-25 20:33 UTC (permalink / raw)


"Randy Brukardt" <randy@rrsoftware.com> writes:

> Does this make sense?

Yes, I think so.  Interesting idea.

- Bob


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

end of thread, other threads:[~2014-07-25 20:33 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-24 20:53 Rationale for this not to compile? Victor Porton
2014-07-24 21:36 ` Adam Beneschan
2014-07-25  5:29   ` Randy Brukardt
2014-07-25 12:19     ` Victor Porton
2014-07-25 12:35       ` AdaMagica
2014-07-25 14:40     ` Robert A Duff
2014-07-25 19:45       ` Randy Brukardt
2014-07-25 20:33         ` Robert A Duff
2014-07-25 13:18 ` Victor Porton

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