comp.lang.ada
 help / color / mirror / Atom feed
* Subprogram Pointer in a Generic
@ 2003-04-17  1:53 Charles H. Sampson
  2003-04-17  2:54 ` James S. Rogers
                   ` (3 more replies)
  0 siblings, 4 replies; 14+ messages in thread
From: Charles H. Sampson @ 2003-04-17  1:53 UTC (permalink / raw)


     I'm using a procedure that takes a procedure pointer as an
argument.  It's pretty standard stuff:

          type Parameterless_Proc_Ptr is access procedure;
          procedure Register (The_Proc : in Parameterless_Proc_Ptr);

     My problem occurs when I want to call this procedure from within a
generic package.  I can't, because 3.10.2(32) says "If the subprogram
denoted by P [the prefix of 'Access] is declared within a generic body,
S [the access-to-subprogram type of the formal parameter] shall be
declared within the generic body."

     Now that's no good for me at all, so I've kludged my way around it
by taking the address of the actual argument procedure and changing it
to a pointer using Unchecked_Conversion, a technique guaranteed to work
for the current version of my current compiler on my current target
machine.

     There are two questions.  (1) What are they trying to prevent by
this restriction?  (2) Is there a more robust way of working around it?

                                Charlie

-- 
     For an email response, my real user name is csampson and my ISP is
inetworld.net.



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  1:53 Subprogram Pointer in a Generic Charles H. Sampson
@ 2003-04-17  2:54 ` James S. Rogers
  2003-04-17  3:15   ` Samuel Tardieu
  2003-04-17  3:12 ` Samuel Tardieu
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 14+ messages in thread
From: James S. Rogers @ 2003-04-17  2:54 UTC (permalink / raw)


"Charles H. Sampson" <claveman@grzorgenplatz.net> wrote in message
news:1ftiuys.1twhum2q9qa00N%claveman@grzorgenplatz.net...
>      I'm using a procedure that takes a procedure pointer as an
> argument.  It's pretty standard stuff:
>
>           type Parameterless_Proc_Ptr is access procedure;
>           procedure Register (The_Proc : in Parameterless_Proc_Ptr);
>
>      My problem occurs when I want to call this procedure from within a
> generic package.  I can't, because 3.10.2(32) says "If the subprogram
> denoted by P [the prefix of 'Access] is declared within a generic body,
> S [the access-to-subprogram type of the formal parameter] shall be
> declared within the generic body."

Why are you passing a procedure access to a generic?

Why not simply pass the procedure as a simple generic parameter:

generic
   with procedure Parameterless_Proc;

This will allow you to call the actual procedure without any of the
issues you describe.

Jim Rogers





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

* Re: Subprogram Pointer in a Generic
  2003-04-17  1:53 Subprogram Pointer in a Generic Charles H. Sampson
  2003-04-17  2:54 ` James S. Rogers
@ 2003-04-17  3:12 ` Samuel Tardieu
  2003-04-17  4:17   ` tmoran
                     ` (2 more replies)
  2003-04-17 19:41 ` Matthew Heaney
  2003-04-17 20:39 ` Robert A Duff
  3 siblings, 3 replies; 14+ messages in thread
From: Samuel Tardieu @ 2003-04-17  3:12 UTC (permalink / raw)


Charles H. Sampson wrote:

>      There are two questions.  (1) What are they trying to prevent by
> this restriction?  (2) Is there a more robust way of working around it?

(1) The absence of such a rule would prevent an implementation from
    implementing efficiently shared generic packages: if, from
    within the body, you take a reference to a local subprogram,
    you do not statically know the accessibility "depth", as the
    generic package may be instantiated locally (from within a
    subprogram for example).  Note that building the access value
    from outside the generic package then storing it is subject to
    the classical static accessibility rules and thus does not
    require this restriction.

However, I must admit that I do not understand why it is not
sufficient for the access to subprogram type to be declared in the
corresponding generic declaration, as both accessibility levels can
be statically compared when compiling the generic package body.

Should this restriction be alleviated in Ada 2005?

(2) If you *know* that you can safely use such a reference, use
    your (non portable) compiler-provided attribute ('Unrestricted_Access
    for GNAT) to create the access value. Another solution would
    be to export the subprogram if not done already and build the
    access value from outside.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/sam



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  2:54 ` James S. Rogers
@ 2003-04-17  3:15   ` Samuel Tardieu
  2003-04-17  5:27     ` tmoran
  0 siblings, 1 reply; 14+ messages in thread
From: Samuel Tardieu @ 2003-04-17  3:15 UTC (permalink / raw)


>>      My problem occurs when I want to call this procedure from within a
>> generic package.  I can't, because 3.10.2(32) says "If the subprogram
>> denoted by P [the prefix of 'Access] is declared within a generic body,
>> S [the access-to-subprogram type of the formal parameter] shall be
>> declared within the generic body."
> 
> Why are you passing a procedure access to a generic?
> 
> Why not simply pass the procedure as a simple generic parameter:

It is the other way around: he wants to call the procedure taking
the access-to-subprogram formal parameter *from* within the body of
the generic package.

  Sam
-- 
Samuel Tardieu -- sam@rfc1149.net -- http://www.rfc1149.net/sam



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  3:12 ` Samuel Tardieu
@ 2003-04-17  4:17   ` tmoran
  2003-04-17 20:24     ` Robert A Duff
  2003-04-18  2:59   ` Charles H. Sampson
  2003-04-22 16:34   ` Warren W. Gay VE3WWG
  2 siblings, 1 reply; 14+ messages in thread
From: tmoran @ 2003-04-17  4:17 UTC (permalink / raw)


>(1) The absence of such a rule would prevent an implementation from
>    implementing efficiently shared generic packages:
Would it be possible to do code sharing at all?
  type Young is range 1 .. 20;
  type Old is range 21 .. 120;
  package a is new generic_package(Young);
  package b is new generic_package(Old);
and inside generic_package you make a call on
Register(Local_Procedure'access);
  What is registered - the instantiation of Local_Procedure that deals
with Young or the one that deals with Old?  Extra information needs to
be passed along, but Register expects just a simple pointer.



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  3:15   ` Samuel Tardieu
@ 2003-04-17  5:27     ` tmoran
  0 siblings, 0 replies; 14+ messages in thread
From: tmoran @ 2003-04-17  5:27 UTC (permalink / raw)


> It is the other way around: he wants to call the procedure taking
> the access-to-subprogram formal parameter *from* within the body of
> the generic package.

> (2) Is there a more robust way of working around it?
  You want to be able to save away a pointer to a procedure?  A tagged
type carries a vector of procedure pointers, so an "access T'class"
is effectively a simple pointer to a list of (one or more) pointers.
The following code registers two instantiations of a generic, one
with a "type T is Positive" and the other with "type T is Boolean".
It then calls the saved registerees, printing for T'image(T'first)
 1
FALSE

package Testr is
  type Registerable_Type is abstract tagged null record;
  procedure Proc(Dummy : Registerable_Type) is abstract;

  type Ptr_To_Registerable_Type is access all Registerable_Type'Class;
  procedure Register(Registeree : Ptr_To_Registerable_Type);

  procedure Call(Index : in Integer);
end Testr;

package body Testr is
  P : array (1 .. 3) of Ptr_To_Registerable_Type;
  N : Natural := 0;

  procedure Register(Registeree : Ptr_To_Registerable_Type) is
  begin
    N := N + 1;
    P(N) := Registeree;
  end Register;

  procedure Call(Index : in Integer) is
  begin
    Proc(P(Index).all);
  end Call;
end Testr;

with Testr;
generic
  type T is (<>);
package Testrg is
  procedure Register_It;
private
  type My_Registerable_Type is new Testr.Registerable_Type with null record;
  procedure Proc(Dummy : My_Registerable_Type);
end Testrg;

with Ada.Text_Io;
package body Testrg is
  Jump_Vector: aliased My_Registerable_Type;

  procedure Proc(Dummy : My_Registerable_Type) is
  begin
    Ada.Text_Io.Put_Line(T'Image(T'First));
  end Proc;

  procedure Register_It is
  begin
    Testr.Register(Jump_Vector'unchecked_access);
  end Register_It;
end Testrg;

with Testrg;
package Testr1 is
  package A is new Testrg(Positive);
  package B is new Testrg(Boolean);
end Testr1;

with Testr1, Testr;
with Ada.Text_Io;
procedure Testr2 is
begin
  Testr1.A.Register_It;
  Testr1.B.Register_It;
  Testr.Call(1);  -- first registeree was A, type T was Positive
  Testr.Call(2);  -- second registeree was B, type T was Boolean
end Testr2;



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  1:53 Subprogram Pointer in a Generic Charles H. Sampson
  2003-04-17  2:54 ` James S. Rogers
  2003-04-17  3:12 ` Samuel Tardieu
@ 2003-04-17 19:41 ` Matthew Heaney
  2003-04-17 20:39 ` Robert A Duff
  3 siblings, 0 replies; 14+ messages in thread
From: Matthew Heaney @ 2003-04-17 19:41 UTC (permalink / raw)


claveman@grzorgenplatz.net (Charles H. Sampson) wrote in message news:<1ftiuys.1twhum2q9qa00N%claveman@grzorgenplatz.net>...
> I'm using a procedure that takes a procedure pointer as an
> argument.  It's pretty standard stuff:
> 
>           type Parameterless_Proc_Ptr is access procedure;
>           procedure Register (The_Proc : in Parameterless_Proc_Ptr);
> 
> 
>      There are two questions.  (1) What are they trying to prevent by
> this restriction?  (2) Is there a more robust way of working around it?

The purpose of subprogram pointers in Ada95 is to implement callbacks,
e.g. for implementing a GUI.  You don't have full downward closures in
Ada95.

If you want to call a subprogram supplied by a caller, then use a
generic formal subprogram instead:

generic
   ...
package GP is 
   generic
      with procedure Op is <>;
   procedure Generic_Call_Op (...);
   ...
end GP;


Another possibility is to import the subprogram as a generic formal
subprogram of the generic package:

   generic
     with procedure Op is <>;
     ...
   package GP is ...;


Perhaps if you provided more information about what you're doing then
maybe we can give some more specific solutions.



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  4:17   ` tmoran
@ 2003-04-17 20:24     ` Robert A Duff
  0 siblings, 0 replies; 14+ messages in thread
From: Robert A Duff @ 2003-04-17 20:24 UTC (permalink / raw)


tmoran@acm.org writes:

> >(1) The absence of such a rule would prevent an implementation from
> >    implementing efficiently shared generic packages:
> Would it be possible to do code sharing at all?
>   type Young is range 1 .. 20;
>   type Old is range 21 .. 120;
>   package a is new generic_package(Young);
>   package b is new generic_package(Old);
> and inside generic_package you make a call on
> Register(Local_Procedure'access);
>   What is registered - the instantiation of Local_Procedure that deals
> with Young or the one that deals with Old?  Extra information needs to
> be passed along, but Register expects just a simple pointer.

It is certainly possible, but Randy Brukardt will tell you it's not
easy, and probably not possible to do efficiently.

- Bob



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  1:53 Subprogram Pointer in a Generic Charles H. Sampson
                   ` (2 preceding siblings ...)
  2003-04-17 19:41 ` Matthew Heaney
@ 2003-04-17 20:39 ` Robert A Duff
  2003-04-17 23:14   ` Randy Brukardt
  3 siblings, 1 reply; 14+ messages in thread
From: Robert A Duff @ 2003-04-17 20:39 UTC (permalink / raw)


claveman@grzorgenplatz.net (Charles H. Sampson) writes:

>      I'm using a procedure that takes a procedure pointer as an
> argument.  It's pretty standard stuff:
> 
>           type Parameterless_Proc_Ptr is access procedure;
>           procedure Register (The_Proc : in Parameterless_Proc_Ptr);
> 
>      My problem occurs when I want to call this procedure from within a
> generic package.  I can't, because 3.10.2(32) says "If the subprogram
> denoted by P [the prefix of 'Access] is declared within a generic body,
> S [the access-to-subprogram type of the formal parameter] shall be
> declared within the generic body."
> 
>      Now that's no good for me at all, so I've kludged my way around it
> by taking the address of the actual argument procedure and changing it
> to a pointer using Unchecked_Conversion, a technique guaranteed to work
> for the current version of my current compiler on my current target
> machine.
> 
>      There are two questions.  (1) What are they trying to prevent by
> this restriction?

First, you can't take 'Access of a nested procedure when the access type
is less nested (nested within procedures, I mean).  That's because you
could then call the procedure after the containing procedure is done, so
the nested one no longer exists (and the variables visible to it no
longer exist).

If you do the 'Access in a generic, the compiler doesn't know (when
compiling the generic) whether the instance will be nested.  The AARM says:

    32.a  Discussion: The part about generic bodies is worded in terms of the
          denoted subprogram, not the denoted view; this implies that renaming
          is invisible to this part of the rule. This rule is partly to
          prevent contract model problems with respect to the accessibility
          rules, and partly to ease shared-generic-body implementations, in
          which a subprogram declared in an instance needs to have a different
          calling convention from other subprograms with the same profile.

>... (2) Is there a more robust way of working around it?

The solution is easy: declare the procedure you're taking 'Access of in
the private part of the generic, rather than in the body.  And don't
instantiate the generic in a nested place.

- Bob



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

* Re: Subprogram Pointer in a Generic
  2003-04-17 20:39 ` Robert A Duff
@ 2003-04-17 23:14   ` Randy Brukardt
  0 siblings, 0 replies; 14+ messages in thread
From: Randy Brukardt @ 2003-04-17 23:14 UTC (permalink / raw)


Robert A Duff wrote in message ...
>If you do the 'Access in a generic, the compiler doesn't know (when
>compiling the generic) whether the instance will be nested.  The AARM
says:
>
>    32.a  Discussion: The part about generic bodies is worded in terms
of the
>          denoted subprogram, not the denoted view; this implies that
renaming
>          is invisible to this part of the rule. This rule is partly to
>          prevent contract model problems with respect to the
accessibility
>          rules, and partly to ease shared-generic-body
implementations, in
>          which a subprogram declared in an instance needs to have a
different
>          calling convention from other subprograms with the same
profile.

Note that this rule was confused in Ada 95 (it prohibited more than
necessary, and didn't prohibit some things that needed to illegal); that
was fixed by AI-229.

The !appendix on that AI gives some more justification for the rule.
There is also an LSN on the subject, which is quoted in AI-254.

>>... (2) Is there a more robust way of working around it?
>
>The solution is easy: declare the procedure you're taking 'Access of in
>the private part of the generic, rather than in the body.  And don't
>instantiate the generic in a nested place.


But that may work right only with a compiler that implements AI-229. The
original rule is more restrictive.

                    Randy.





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

* Re: Subprogram Pointer in a Generic
  2003-04-17  3:12 ` Samuel Tardieu
  2003-04-17  4:17   ` tmoran
@ 2003-04-18  2:59   ` Charles H. Sampson
  2003-04-22 16:34   ` Warren W. Gay VE3WWG
  2 siblings, 0 replies; 14+ messages in thread
From: Charles H. Sampson @ 2003-04-18  2:59 UTC (permalink / raw)


Samuel Tardieu <sam@rfc1149.net> wrote:

> Charles H. Sampson wrote:
> 
> >      There are two questions.  (1) What are they trying to prevent by
> > this restriction?  (2) Is there a more robust way of working around it?
> 
> (1) The absence of such a rule would prevent an implementation from
>     implementing efficiently shared generic packages: if, from
>     within the body, you take a reference to a local subprogram,
>     you do not statically know the accessibility "depth", as the
>     generic package may be instantiated locally (from within a
>     subprogram for example).  Note that building the access value
>     from outside the generic package then storing it is subject to
>     the classical static accessibility rules and thus does not
>     require this restriction.

     That explains the reason for the rule, I think, but the rule 
invalidates one of the long-established folk properties of generics, 
that an instantiation of a generic has the same properties as if the 
thing (package or subprogram) had been written out in full.

     I'm not up on the shared code of generics but I think you're 
saying something like this.  With shared code in effect, each call 
into a package instantiation causes the instantiation's data spaces to 
be set up.  If this is the case, then what I want to do wouldn't work 
because when the ultimate call on the local procedure is made the 
setting up of the data space wouldn't occur because it is a local 
procedure.

     Whatever the mechanism, it seems that there is a solution that 
would give me what I want.  The instantiation must be able to handle 
the case where the subject procedure, the one to which 'Access is 
applied, is declared in the specification of the generic package.  
That procedure can be called both from outside the package and from 
within.  So, whatever the mechanism for code sharing in generics, all 
the compiler has to do is handle the local procedure as though it were 
also declared in the specification.

> 
> However, I must admit that I do not understand why it is not
> sufficient for the access to subprogram type to be declared in the
> corresponding generic declaration, as both accessibility levels can
> be statically compared when compiling the generic package body.
> 
> Should this restriction be alleviated in Ada 2005?

     I think so, not only for my particular application but so the
folk property would be true again.
> 
> (2) If you *know* that you can safely use such a reference, use
>     your (non portable) compiler-provided attribute ('Unrestricted_Access
>     for GNAT) to create the access value. Another solution would
>     be to export the subprogram if not done already and build the
>     access value from outside.

     The problem with the first suggestion is that I'm trying to come 
up with a portable solution, so use of a compiler-specific attribute 
isn't going to help.  Besides, not all compilers have such attributes.

     The second suggestion is an acceptable one.  Talk about not seeing
the obvious!  I'm trying to solve a very application-specific problem 
with this registration process.  My "solution" had a nice side-effect 
that the subject procedures didn't have to be made global when their 
scope of use is very small.  However, making them global and getting 
fully portable code is far better than the kludge I came up with.

                                Charlie


-- 
     For an email response, my real user name is csampson and my ISP is
inetworld.net.



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

* Re: Subprogram Pointer in a Generic
  2003-04-17  3:12 ` Samuel Tardieu
  2003-04-17  4:17   ` tmoran
  2003-04-18  2:59   ` Charles H. Sampson
@ 2003-04-22 16:34   ` Warren W. Gay VE3WWG
  2003-04-22 21:17     ` Robert A Duff
  2 siblings, 1 reply; 14+ messages in thread
From: Warren W. Gay VE3WWG @ 2003-04-22 16:34 UTC (permalink / raw)


Samuel Tardieu wrote:
> Charles H. Sampson wrote:
>>     There are two questions.  (1) What are they trying to prevent by
>>this restriction?  (2) Is there a more robust way of working around it?
> 
> (1) The absence of such a rule would prevent an implementation from
>     implementing efficiently shared generic packages: if, from
>     within the body, you take a reference to a local subprogram,
>     you do not statically know the accessibility "depth", as the
>     generic package may be instantiated locally (from within a
>     subprogram for example).  Note that building the access value
>     from outside the generic package then storing it is subject to
>     the classical static accessibility rules and thus does not
>     require this restriction.
> 
> However, I must admit that I do not understand why it is not
> sufficient for the access to subprogram type to be declared in the
> corresponding generic declaration, as both accessibility levels can
> be statically compared when compiling the generic package body.
> 
> Should this restriction be alleviated in Ada 2005?

I think so. I found this to be a horrible limitation when it
was necessary to register a callback from within a generic.

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




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

* Re: Subprogram Pointer in a Generic
  2003-04-22 16:34   ` Warren W. Gay VE3WWG
@ 2003-04-22 21:17     ` Robert A Duff
  2003-04-23 20:46       ` Warren W. Gay VE3WWG
  0 siblings, 1 reply; 14+ messages in thread
From: Robert A Duff @ 2003-04-22 21:17 UTC (permalink / raw)


"Warren W. Gay VE3WWG" <ve3wwg@cogeco.ca> writes:

> I think so. I found this to be a horrible limitation when it
> was necessary to register a callback from within a generic.

Why?  Declaring something in the private part of the generic package is
roughly the same thing as putting it in the body.  It's not *exactly*
the same, but close enough.

And it has little effect on compile times, if the compiler is not
sharing code (which is the usual case).

- Bob



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

* Re: Subprogram Pointer in a Generic
  2003-04-22 21:17     ` Robert A Duff
@ 2003-04-23 20:46       ` Warren W. Gay VE3WWG
  0 siblings, 0 replies; 14+ messages in thread
From: Warren W. Gay VE3WWG @ 2003-04-23 20:46 UTC (permalink / raw)


Robert A Duff wrote:
> "Warren W. Gay VE3WWG" <ve3wwg@cogeco.ca> writes:
>>I think so. I found this to be a horrible limitation when it
>>was necessary to register a callback from within a generic.
> 
> Why?  Declaring something in the private part of the generic package is
> roughly the same thing as putting it in the body.  It's not *exactly*
> the same, but close enough.
> 
> And it has little effect on compile times, if the compiler is not
> sharing code (which is the usual case).
> 
> - Bob

Well, all I know is that GNAT didn't like it. I had to find
another way. I didn't have time to deliberate about it. Even now,
I don't have the time to fuss with it.

-- 
Warren W. Gay VE3WWG
http://home.cogeco.ca/~ve3wwg




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

end of thread, other threads:[~2003-04-23 20:46 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-04-17  1:53 Subprogram Pointer in a Generic Charles H. Sampson
2003-04-17  2:54 ` James S. Rogers
2003-04-17  3:15   ` Samuel Tardieu
2003-04-17  5:27     ` tmoran
2003-04-17  3:12 ` Samuel Tardieu
2003-04-17  4:17   ` tmoran
2003-04-17 20:24     ` Robert A Duff
2003-04-18  2:59   ` Charles H. Sampson
2003-04-22 16:34   ` Warren W. Gay VE3WWG
2003-04-22 21:17     ` Robert A Duff
2003-04-23 20:46       ` Warren W. Gay VE3WWG
2003-04-17 19:41 ` Matthew Heaney
2003-04-17 20:39 ` Robert A Duff
2003-04-17 23:14   ` Randy Brukardt

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