* 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 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: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 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 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 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 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
* 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 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
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