lazear@MITRE.ARPA (Walt Lazear) (10/22/85)
This may seem a naive question, since at first look it seems impossible: can I (in Ada) pass the name (address) of a procedure to another procedure to be executed by that called procedure? My goal is to have a general procedure that will call the supplied procedure until certain well-defined conditions occur, then return to the original caller. It is trivial to do in C, but I cannot find anything comparable in Ada. Thanks for any help. Walt (Lazear at MITRE.ARPA)
prindle@NADC.ARPA (10/22/85)
This subject was discussed at quite some length over a year ago on this list (you might hunt down the archives). The gist of the discussion was that it could be done by making the procedure that is to call another procedure generic, with an instantiation parameter to define the procedure to be called. The top level calling procedure then instantiates the generic once for each different procedure that the generic must call, then calls the proper instantiated procedure at the proper time. My opposition to this solution was that if multiple procedures were to be called, multiple copies of the generic differing only in the procedure called from within itself would be produced. The rebuttal to this argument was that any reasonable compiler would handle such instantiations by simply passing a hidden argument to the middle procedure which was the address of the final procedure to be called (which, of course, is what everyone wanted to do in the first place, but couldn't figure out how to). Now the only problem is "where is this *reasonable* compiler?". The ALS compiler openly admits that there is no code sharing between instantiations of the same generic; sort of leavs the question open, doesn't it! Perhaps others can tell this list how their "favorite" Ada compiler handles multiple instantiations of a generic where the only generic parameters are functions/procedures to be called (i.e. is a hidden parameter passed for each function, is the code fully duplicated, or perhaps something even more exciting done?). Frank Prindle Prindle@NADC
Geoff_Mendal@UMICH-MTS.MAILNET (10/23/85)
>This may seem a naive question, since at first look it seems impossible: >can I (in Ada) pass the name (address) of a procedure to another procedure >to be executed by that called procedure? My goal is to have a general >procedure that will call the supplied procedure until certain well-defined >conditions occur, then return to the original caller. It is trivial to do >in C, but I cannot find anything comparable in Ada. Thanks for any help. Perhaps a generic subprogram with a formal subprogram parameter will accomplish what you want. Consider the following simple example: generic with procedure Supplied_Procedure; procedure General_Procedure; . . . procedure General_Procedure is begin -- perhaps do something here Supplied_Procedure; -- perhaps do something here end General_Procedure; All you need to do is instantiate the General_Procedure with the name of a "supplied" procedure which you wish the General_Procedure to call. For example, the following instantiation of General_Procedure will cause "Hello" to be printed by a "supplied" procedure. with General_Procedure, Text_Io; procedure Main is procedure Print_Hello is begin Text_Io.Put_Line("Hello"); end Print_Hello; procedure My_General_Procedure is new General_Procedure(Print_Hello); begin My_General_Procedure; end Main; For simplicity, the above example assumes neither General_Procedure nor its formal subprogram parameter pass any parameters. Passing parameters can also be done, but the parameters of a generic formal subprogram must match those of the actual subprogram. Hence, one can only use the above method to "pass" subprograms that match the generic formal subprogram's parameter profile. If generics don't do what you want, there might be another way, using address clauses. I DO NOT ADVOCATE THIS METHOD. In fact, the ARM states that doing so makes a program erroneous [ARM 13.5(8)]. Address clauses need not even be implemented. With this in mind, consider the following: with system; procedure General_Procedure(Some_Procedure_Address : in System.Address) is procedure Supplied_Procedure; for Supplied_Procedure use at Some_Procedure_Address; begin -- perhaps do something here Supplied_Procedure; -- perhaps do something here end General_Procedure; . . . with General_Procedure, Text_Io; procedure Main is procedure Print_Hello is begin Text_Io.Put_Line("Hello"); end Print_Hello; begin General_Procedure(Print_Hello'Address); end Main; I doubt that this method would ever work in practice. I have yet to find an implementation that will even compile/execute this second (erroneous) method without blowing up (maybe that's an omen). Geoff Mendal, Stanford U.
Berlen_Oronzo@QZCOM.MAILNET (10/25/85)
No you cannot pass any subprogram as a parameter using ADA. It is due to another approach respect 'C' Programming Language. One of ADA goals is to have a reliable and readable too to develop programs , then it is impossible to do Berlen Oronzo CSATA Italy
jbn@wdl1.UUCP (10/26/85)
The Verdix Ada compiler (5.0 Beta, SUN) allows sharing of generic package bodies, but only if the generic parameters are restricted to enumeration tpes, integer types, and floating types, and the pragma SHARE_BODY is used. But it doesn't work for generics with procedure parameters. Considering that procedure parameters with full type checking are provided for in the ISO Pascal standard (although not in Jensen and Wirth) it's suprising that this was left out of Ada. John Nagle
macrakis@HARVARD.HARVARD.EDU (Stavros Macrakis) (10/28/85)
> >can I...pass the name (address) of a procedure to another procedure...? > >[I want to] call the supplied procedure until certain well-defined > >conditions occur.... > Perhaps a generic subprogram with a formal subprogram parameter ... Yes, a generic procedure appears to be exactly what is needed here. > If generics don't do what you want, there might be another way, using > address clauses. I DO NOT ADVOCATE THIS METHOD. In fact, the ARM states > that doing so makes a program erroneous [ARM 13.5(8)]. ... > procedure General_Procedure(Some_Procedure_Address : in System.Address) is > procedure Supplied_Procedure; > for Supplied_Procedure use at Some_Procedure_Address; > begin ... > I doubt that this method would ever work in practice. I have yet to find an > implementation that will even compile/execute this second (erroneous) method > without blowing up (maybe that's an omen). Actually, this appears to be illegal: `For each subprogram declaration, there must be a corresponding body (except for a subprogram written in another language, as explained in section 13.9).' [RM 6.3/3] Note that an explicit reference is made to chapter 13 for the pragma Interface case, but not for address clauses. A problem with the wording of 13.5 is that it says `An address clause specifies a required address in storage for an entity.' I suspect this is intended to mean `where an entity is to be placed' rather than `where an entity should be considered to be'. -s