comp.lang.ada
 help / color / mirror / Atom feed
* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
                   ` (3 preceding siblings ...)
  1999-06-25  0:00 ` tmoran
@ 1999-06-25  0:00 ` Ehud Lamm
  1999-06-26  0:00 ` David C. Hoos, Sr.
  5 siblings, 0 replies; 14+ messages in thread
From: Ehud Lamm @ 1999-06-25  0:00 UTC (permalink / raw)


Usually with 'unrestricted_access (only in GNAT...)

Kills the protability of my frameworks, but this is how I do it these day.

Ehud Lamm     mslamm@pluto.mscc.huji.ac.il





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

* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
@ 1999-06-25  0:00 ` Ted Dennison
  1999-06-25  0:00 ` David Botton
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: Ted Dennison @ 1999-06-25  0:00 UTC (permalink / raw)


In article <37737285.5CF9ED5F@Maths.UniNe.CH>,
  Gautier <Gautier.deMontmollin@Maths.UniNe.CH> wrote:

> *But* whatever the way I nest and subtype the things, the compiler
> (GNAT) tells me (certainly with good reasons):
>
> "subprogram must not be deeper than access type"
>
> even when it doesn't seem depper at all! So, my question is:
> how to do it ?

Heh. I stumbled into the same problem about a year ago when I was first
working on OpenToken. (I'm pretty sure it really is the same problem
this time. :-)  ). OpenToken uses procedure accesses to allow users to
supply their own text feeder functions; a rough equivalent to lex's
"input()" routine.

What had confused me was that it seemed like a procedure declared in the
main procedure should be at the same "level" as a procedure (or access
type) declared in a package spec/body. However, that is not the case. In
fact, someone was kind enough to point out that it is quite possible to
call the main procedure recursively.

Requiring that folks use "'Unchecked_Access" or declare the accessed
procedure in a package spec is really not all that bad. I've found that
kind of restriction is really more of a pain for my test drivers than it
is for actual client code.

One slightly different approach that OpenToken takes is to declare the
access type inside of a *generic* package. That way you only have to
worry about the "level" of the procedure being as high as the
*instantiation* of the generic. If any other part of your package would
make sense as a generic, you may consider this approach.

--
T.E.D.


Sent via Deja.com http://www.deja.com/
Share what you know. Learn what you don't.




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

* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
                   ` (2 preceding siblings ...)
  1999-06-25  0:00 ` David Botton
@ 1999-06-25  0:00 ` tmoran
  1999-06-26  0:00   ` Gautier
  1999-06-25  0:00 ` Ehud Lamm
  1999-06-26  0:00 ` David C. Hoos, Sr.
  5 siblings, 1 reply; 14+ messages in thread
From: tmoran @ 1999-06-25  0:00 UTC (permalink / raw)


>"subprogram must not be deeper than access type"
>even when it doesn't seem depper at all!
  Your "main program" is in fact a procedure, and
procedure My_feedback is inside that (main program) procedure.
  Consider what would happen if you started up another task,
passed an access to My_feedback to it, and then let the "main program"
go to completion.  The task would then be able to call My_feedback,
which might try to use variables declared in "procedure main_program",
but those variables no longer exist.

>So, my question is: how to do it ?
How about adding a dummy tagged type parameter to Extract, where Extract's
"proc" call dispatches on the dummy tagged type.  eg something like:

modify Extract's spec to
package whatever is
...
  type feedback_selector is abstract tagged null record;
  procedure proc ( Which_Feedback : in out feedback_selector;
                   percents_done: natural; user_abort: out boolean)
    is abstract;

  procedure Extract(from : zip_info; what : String;
                    method     : out pkzip_method;
                    feedback   : feedback_selector'class);
 \x7f
and inside of Extract, make calls on

    proc(feedback, percents_done=>xxx, user_abort=>yyy);

which will call the "proc" procedure for the particular "feedback".

Then any time you need to make one or more particular feedback procs

  package feedback_handlers is
...
    type My_feedback is new whatever.feedback_selector;
    procedure proc ( Which_Feedback : in out My_feedback;
                     percents_done: natural; user_abort: out boolean);

    type Your_feedback is new whatever.feedback_selector;
    procedure proc ( Which_Feedback : in out Your_feedback;
                     percents_done: natural; user_abort: out boolean);
...
  end feedback_handlers;
  package body feedback_handlers is
    procedure proc ( Which_Feedback : in out My_feedback;
                     percents_done: natural; user_abort: out boolean) is
    new_done_dots: natural:= (dots * percents_done) / 100;
    begin
      for i in done_dots .. new_done_dots loop
        Put('.');
      end loop;
      user_abort:= false;
    end proc;
    procedure proc ( Which_Feedback : in out Your_feedback;
                     percents_done: natural; user_abort: out boolean) is
...
  end feedback_handlers;

and to use them

  procedure Do_Unzip is
      Feedback1 : feedback_handlers.My_feedback;
      Feedback2 : feedback_handlers.Your_feedback;  -- for instance
    begin
...
          whatever.Extract(zi, Argument(i), method, Feedback1 );
...
    end Do_unzip;

(typed but not tested)

>NB: a generic solution doesn't seem a solution as some packages,
>basically non-generic, have to call the feedback procedure; making
  Those packages would just 'with whatever' and take a
whatever.feedback_selector'class parameter.  To call one of those
routines with a specific proc in mind, just pass it an object of
the appropriate kind.  Essentially, instead of passing "proc1'access"
or "proc2'access", you pass in Feedback1 or Feedback2, or ...




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

* Access to procedures
@ 1999-06-25  0:00 Gautier
  1999-06-25  0:00 ` Ted Dennison
                   ` (5 more replies)
  0 siblings, 6 replies; 14+ messages in thread
From: Gautier @ 1999-06-25  0:00 UTC (permalink / raw)


Hello, Reference Manual gurus!

I've encountered a stupid but sticky problem by implementing my
Unzip-Ada project. In the interactive versions of extract procedures,
I pass an access to a feedback procedure for display & interaction.

*But* whatever the way I nest and subtype the things, the compiler
(GNAT) tells me (certainly with good reasons):

"subprogram must not be deeper than access type"

even when it doesn't seem depper at all! So, my question is:
how to do it ?

The code in question is :

* in Unzip package spec :

 type feedback_proc is access
   procedure ( percents_done: in natural; user_abort: out boolean );

  procedure Extract(from : zip_info; what : String;
                    method     : out pkzip_method;
                    feedback   : feedback_proc );

* in a main program (one of many attempts!) :

  subtype local_feedback_proc is feedback_proc;

  procedure My_feedback( percents_done: natural; user_abort: out boolean
) is
    new_done_dots: natural:= (dots * percents_done) / 100;
    begin
      for i in done_dots .. new_done_dots loop
        Put('.');
      end loop;
      user_abort:= false;
    end My_feedback;

  -- My_feedback_access: constant local_feedback_proc:= My_feedback'access;

  procedure Do_Unzip is
    begin
...
          Extract( zi, Argument(i), method, My_feedback_access );
    end Do_unzip;

NB: a generic solution doesn't seem a solution as some packages,
basically non-generic, have to call the feedback procedure; making
the whole generic could become heavy.

-- 
Gautier

--------
http://members.xoom.com/gdemont/




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

* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
  1999-06-25  0:00 ` Ted Dennison
  1999-06-25  0:00 ` David Botton
@ 1999-06-25  0:00 ` David Botton
  1999-06-25  0:00 ` tmoran
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: David Botton @ 1999-06-25  0:00 UTC (permalink / raw)


Try using XXXX'Unrestricted_Access on them.

David Botton

Gautier wrote in message <37737285.5CF9ED5F@Maths.UniNe.CH>...
>Hello, Reference Manual gurus!
>
>I've encountered a stupid but sticky problem by implementing my
>Unzip-Ada project. In the interactive versions of extract procedures,
>I pass an access to a feedback procedure for display & interaction.
>
>*But* whatever the way I nest and subtype the things, the compiler
>(GNAT) tells me (certainly with good reasons):
>
>"subprogram must not be deeper than access type"
>
>even when it doesn't seem depper at all! So, my question is:
>how to do it ?







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

* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
  1999-06-25  0:00 ` Ted Dennison
@ 1999-06-25  0:00 ` David Botton
  1999-06-25  0:00 ` David Botton
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 14+ messages in thread
From: David Botton @ 1999-06-25  0:00 UTC (permalink / raw)


You could also move your main's My_feedback procedure to library level and
that would solve the problem.

David Botton


Gautier wrote in message <37737285.5CF9ED5F@Maths.UniNe.CH>...
>Hello, Reference Manual gurus!
>
>I've encountered a stupid but sticky problem by implementing my
>Unzip-Ada project. In the interactive versions of extract procedures,
>I pass an access to a feedback procedure for display & interaction.
>
>*But* whatever the way I nest and subtype the things, the compiler
>(GNAT) tells me (certainly with good reasons):
>
>"subprogram must not be deeper than access type"
>
>even when it doesn't seem depper at all! So, my question is:
>how to do it ?
>
>The code in question is :
>
>* in Unzip package spec :
>
> type feedback_proc is access
>   procedure ( percents_done: in natural; user_abort: out boolean );
>
>  procedure Extract(from : zip_info; what : String;
>                    method     : out pkzip_method;
>                    feedback   : feedback_proc );
>
>* in a main program (one of many attempts!) :
>
>  subtype local_feedback_proc is feedback_proc;
>
>  procedure My_feedback( percents_done: natural; user_abort: out boolean
>) is
>    new_done_dots: natural:= (dots * percents_done) / 100;
>    begin
>      for i in done_dots .. new_done_dots loop
>        Put('.');
>      end loop;
>      user_abort:= false;
>    end My_feedback;
>
>  -- My_feedback_access: constant local_feedback_proc:= My_feedback'access;
>
>  procedure Do_Unzip is
>    begin
>...
>          Extract( zi, Argument(i), method, My_feedback_access );
>    end Do_unzip;
>
>NB: a generic solution doesn't seem a solution as some packages,
>basically non-generic, have to call the feedback procedure; making
>the whole generic could become heavy.
>
>--
>Gautier
>
>--------
>http://members.xoom.com/gdemont/






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

* Re: Access to procedures
  1999-06-25  0:00 Access to procedures Gautier
                   ` (4 preceding siblings ...)
  1999-06-25  0:00 ` Ehud Lamm
@ 1999-06-26  0:00 ` David C. Hoos, Sr.
  5 siblings, 0 replies; 14+ messages in thread
From: David C. Hoos, Sr. @ 1999-06-26  0:00 UTC (permalink / raw)



Gautier <Gautier.deMontmollin@Maths.UniNe.CH> wrote in message
news:37737285.5CF9ED5F@Maths.UniNe.CH...
> Hello, Reference Manual gurus!
>
> I've encountered a stupid but sticky problem by implementing my
> Unzip-Ada project. In the interactive versions of extract procedures,
> I pass an access to a feedback procedure for display & interaction.
>
> *But* whatever the way I nest and subtype the things, the compiler
> (GNAT) tells me (certainly with good reasons):
>
> "subprogram must not be deeper than access type"
>
> even when it doesn't seem depper at all! So, my question is:
> how to do it ?

The problem is that a compiler cannot know that your main procedure
is always a main procedure -- i.e., that the feedback subprogram will
have the same lifetime as the whole program.  In other words, a
nested subprogram exists only while the subprogram within which
it is nested is executing.

Even if the compiler could know that your main procedure is
the main program, if the compiler follows the implementation advice
of the RM in B.1 (39) (as gnat does), the main program no longer
exists during the execution of adafinal -- so if any finalization
code needed to call your feedback procedure, the feedback procedure
would not exist.

So to guarantee that a subprogram always exists (i.e., is callable
via an access type), the subprogram must be declared at library level --
either as a subprogram declared in its own compilation unit, or
within a package which itself is declared at library level -- i.e,
where the package has a lifetime as long as the program.

The package does not need to be an outer level package -- e.g.,
the package's specification could be declared within the specification
of an outer level package.

I hope this gives some insight into the problem.







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

* Re: Access to procedures
  1999-06-25  0:00 ` tmoran
@ 1999-06-26  0:00   ` Gautier
  1999-06-26  0:00     ` Brian Rogoff
  1999-06-26  0:00     ` tmoran
  0 siblings, 2 replies; 14+ messages in thread
From: Gautier @ 1999-06-26  0:00 UTC (permalink / raw)
  To: tmoran

Thank you for your suggestion - the idea is valuable.

In that precise context, I want to avoid making this
small unzip library depend even on the _existence_
of all that feedbacks because an intended
usage is a complete "invisible" unpacking, allowing
programs to load data from a zipped one.

The "unrestricted_access" way seems much more simple,
though - it seems - only provided by GNAT presently.

It avoids changing "with" clauses in sources or
creating dummy feedback handlers...

-- 
Gautier

--------
http://members.xoom.com/gdemont/




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

* Re: Access to procedures
  1999-06-26  0:00   ` Gautier
  1999-06-26  0:00     ` Brian Rogoff
@ 1999-06-26  0:00     ` tmoran
  1999-06-27  0:00       ` David Botton
  1 sibling, 1 reply; 14+ messages in thread
From: tmoran @ 1999-06-26  0:00 UTC (permalink / raw)


>>   procedure Do_Unzip is
>>       Feedback1 : feedback_handlers.My_feedback;
>> ....
>>           whatever.Extract(zi, Argument(i), method, Feedback1 );
>In that precise context, I want to avoid making this
>small unzip library depend even on the _existence_
>of all that feedbacks because an intended
>usage is a complete "invisible" unpacking, allowing
>programs to load data from a zipped one.
  Why not make the feedback parameter to Extract have a default
expression?  The default tagged object, defined in the package
defining Extract, can have no-op's for its Proc.  Then if
someone doesn't use it, or doesn't even know it exists, fine.
             whatever.Extract(zi, Argument(i), method);

>The "unrestricted_access" way seems much more simple,
>though - it seems - only provided by GNAT presently.
  The access restrictions, as previously pointed out, are there
for a reason.  IMHO, if you use "unrestricted_access", you are
living dangerously and creating a potential trap for future,
less careful, users of your Extract package.  Not to mention it
becomes non-standard Ada, tied to one particular compiler.




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

* Re: Access to procedures
  1999-06-26  0:00   ` Gautier
@ 1999-06-26  0:00     ` Brian Rogoff
  1999-06-26  0:00     ` tmoran
  1 sibling, 0 replies; 14+ messages in thread
From: Brian Rogoff @ 1999-06-26  0:00 UTC (permalink / raw)


On Sat, 26 Jun 1999, Gautier wrote:

> Thank you for your suggestion - the idea is valuable.

That was an instance of the Command pattern in patternspeak, though the 
GoF book says that some C++ folk call it a "functor". While I've heard
this usage of functor, I don't like it (ML bigotry :-).  

> In that precise context, I want to avoid making this
> small unzip library depend even on the _existence_
> of all that feedbacks because an intended
> usage is a complete "invisible" unpacking, allowing
> programs to load data from a zipped one.
> 
> The "unrestricted_access" way seems much more simple,
> though - it seems - only provided by GNAT presently.

Well, I suppose there is an argument that using this non-portable feature 
will pressure other vendors to provide it, or a similar feature. GNAT has 
quite a few improvements over pure Ada. 

-- Brian






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

* Re: Access to procedures
  1999-06-27  0:00       ` David Botton
@ 1999-06-27  0:00         ` Brian Rogoff
  1999-06-27  0:00           ` tmoran
  0 siblings, 1 reply; 14+ messages in thread
From: Brian Rogoff @ 1999-06-27  0:00 UTC (permalink / raw)


On Sun, 27 Jun 1999, David Botton wrote:
> I don't believe he was looking to use it as part of his code, but rather as
> an option for test drivers or those that wish to use his packages.
> 
> Any serious code is going to include library level functions, etc that would
> eliminate a need for Unrestricted_Access.

I could find lots of uses for nested function arguments. There are
workarounds in standard Ada; lifting the subprograms to library level, 
smuggling (good one je!) access types to the right level, command pattern, 
etc., they are all suboptimal when you simply want to pass a function as 
an argument, and not even return it in a variable. 

> When working on my GUI classes, I have been a VERY happy camper to have
> Unrestricted_Access around for quick testing and even for small little apps
> that use the classes.

If it makes you a happy camper, how can it be bad? 

Seriously, I know that Unrestricted_Access is a broader mechanism than
just downward funargs, but that simple capability is missed. 

-- Brian





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

* Re: Access to procedures
  1999-06-27  0:00         ` Brian Rogoff
@ 1999-06-27  0:00           ` tmoran
  1999-06-28  0:00             ` Gautier
  0 siblings, 1 reply; 14+ messages in thread
From: tmoran @ 1999-06-27  0:00 UTC (permalink / raw)


>> When working on my GUI classes, I have been a VERY happy camper to have
>> Unrestricted_Access around for quick testing and even for small little apps
>> that use the classes.
>
>If it makes you a happy camper, how can it be bad?
  If it feels good at the time, it must be good?
How about "Use Unrestricted_Access when appropriate, but don't
make a habit of it".  There are almost always better ways to solve
the problem.  Practice learning and using them.




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

* Re: Access to procedures
  1999-06-26  0:00     ` tmoran
@ 1999-06-27  0:00       ` David Botton
  1999-06-27  0:00         ` Brian Rogoff
  0 siblings, 1 reply; 14+ messages in thread
From: David Botton @ 1999-06-27  0:00 UTC (permalink / raw)


I don't believe he was looking to use it as part of his code, but rather as
an option for test drivers or those that wish to use his packages.

Any serious code is going to include library level functions, etc that would
eliminate a need for Unrestricted_Access.

When working on my GUI classes, I have been a VERY happy camper to have
Unrestricted_Access around for quick testing and even for small little apps
that use the classes.

David Botton


tmoran@bix.com wrote in message <7l34od$3b0@lotho.delphi.com>...
>IMHO, if you use "unrestricted_access", you are
>living dangerously and creating a potential trap for future,
>less careful, users of your Extract package.  Not to mention it
>becomes non-standard Ada, tied to one particular compiler.






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

* Re: Access to procedures
  1999-06-27  0:00           ` tmoran
@ 1999-06-28  0:00             ` Gautier
  0 siblings, 0 replies; 14+ messages in thread
From: Gautier @ 1999-06-28  0:00 UTC (permalink / raw)


> How about "Use Unrestricted_Access when appropriate, but don't
> make a habit of it".  There are almost always better ways to solve
> the problem.  Practice learning and using them.

I'll put a word about it in the "readme". Note that the library
itself doesn't use "unrestricted_access"; it's even almost Ada83:
the previous versions did compile under DEC Ada!

-- 
Gautier




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

end of thread, other threads:[~1999-06-28  0:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-06-25  0:00 Access to procedures Gautier
1999-06-25  0:00 ` Ted Dennison
1999-06-25  0:00 ` David Botton
1999-06-25  0:00 ` David Botton
1999-06-25  0:00 ` tmoran
1999-06-26  0:00   ` Gautier
1999-06-26  0:00     ` Brian Rogoff
1999-06-26  0:00     ` tmoran
1999-06-27  0:00       ` David Botton
1999-06-27  0:00         ` Brian Rogoff
1999-06-27  0:00           ` tmoran
1999-06-28  0:00             ` Gautier
1999-06-25  0:00 ` Ehud Lamm
1999-06-26  0:00 ` David C. Hoos, Sr.

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