comp.lang.ada
 help / color / mirror / Atom feed
* subprogram must not be deeper than access type
@ 2011-09-25  9:02 Natasha Kerensikova
  2011-09-25 14:04 ` Oliver Kleinke
                   ` (3 more replies)
  0 siblings, 4 replies; 42+ messages in thread
From: Natasha Kerensikova @ 2011-09-25  9:02 UTC (permalink / raw)


Hello,

I'm encountering the error in the subject, "subprogram must not be
deeper than access type", and while I understand what it means in
general and the rationale, I'm lost on why it applies to my code and how
to work around it.

However, instead of just copying code, I will first explain the problem
I'm trying to solve, maybe there is a better a way to deal with it
"upstream" from the error. Still, I would love to understand how the
error applies to this case, for my personal Ada edification.


So the general context is that I'm in the last stages of teaching myself
Ada, and at this point I though it would be a good idea to reimplement
something I wrote in C, with a few improvements on the design coming
from the experience. The rationale was to spend little time on the
"software design" part, so that I can focus on learning to write correct
Ada.

In the C project the performance bottleneck was the time spent to append
relatively short strings to an ever-growing buffer, and I was hoping
that with a design so close, the Ada project would encounter the same
problem. So I decided to create a String_Accumulator interface, which
basically contains Append, To_String, Reset and a few other upkeep
subprograms, and I started writing the project using
String_Accumulator'Class. Another rationale for this approach (although
it came after the fact) is that it makes it easy to enforce bounds on
the amount of intermediate memory used when dealing with untrusted
input.

Then at some point I realized it would make the project clearer if I
also had a String_Accumulator_Stack interface, with Push and Pop extra
procedures, and apply other operations to the topmost element.

Then I wanted to try all this for real, and for that I needed classes
that implement the interfaces. So I wrote something straightforward for
String_Accumulator, based on Unbounded_String. String_Accumulator_Stack
was based on Indefinite_Doubly_Linked_Lists of String_Accumulator'Class
and less straightforward to write (there was a lot of nested subprograms
and Update_Element). I only lacked something to create the
String_Accumulator'Class objects when the stack grows.

To keep the stack flexible (because different stack level might have
different usage pattern) I decided to use a callback:

type Accumulator_Builder is not null
   access function (Depth : Positive) return String_Accumulator'Class;

Then the simplest way I imagined to make it accessible without revealing
the internals was:

type String_Accumulator_Linked_List (Builder : Accumulator_Builder)
   is new String_Accumulator_Stack with private;

Everything compiled, so I thought it was fine.

Things started to go wrong only when I tried to create an object of such
type... It looks like that:

procedure Main is
   function Builder (Depth : Positive)
      return String_Accumulator'Class
   is
      pragma Unrefenced (Depth);
   begin
      return Unbounded_String_Accumulator.Empty_Accumulator;
   end Builder;

   Output : String_Accumulator_Linked_List (Builder'Access);
begin
   null;  --  or actually, real code.
end Main;

And GNAT refused to compile it, because "subprogram must not be deeper
than access type".

So I imagined that since Builder and Output have the same lifetime, it
might not be so well-define which will cease to exist first. So while
not strictly deeper, being as deep can be a problem.

procedure Main is
   function Builder -- exactly the same as before
begin
   declare
      Output : String_Accumulator_Linked_List (Buidler'Access);
   begin
      null;  --  or actually real code
   end;
end Main;

Unless I'm missing something, Output lifetime is not guaranteed to be
longer than that of Builder. But GNAT still refuses it compile it, still
with "subprogram must not be deeper than access type".

So I guessed that the discriminant being part of the type, I'm
effectively creating a type that rely on Builder existence, and maybe
the type has a lifetime unrelated to the lifetime of objects of that
type.

So instead I changed the linked list type:

type SALL_Internal is private;
type String_Accumulator_Linked_List is new String_Accumulator_Stack
   with record
      Builder : Accumulator_Builder;
      Internal : SALL_Internal;
   end record;

along with the following declaration in Main:
   Output : String_Accumulator_Linked_List (Builder => Builder'Access,
                                            others => <>);

I tried both with and without the extra declare block, and GNAT still
rejects both with "subprogram must not be deeper than access type".

So then I tried putting the Builder function in the
Unbounded_String_Accumulator package, but all above 4 possibilities were
still rejected by GNAT the same way.

So then I got so horribly lost and desperate about the error that I
dared post here.


Would you have any idea of what is going there or what I am doing wrong?
Or should I try to craft a smaller test case and post it?


Thanks in advance for your help,
Natasha



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

end of thread, other threads:[~2011-10-04 18:40 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-25  9:02 subprogram must not be deeper than access type Natasha Kerensikova
2011-09-25 14:04 ` Oliver Kleinke
2011-09-26  9:35   ` Natasha Kerensikova
2011-10-03 23:30   ` Yannick Duchêne (Hibou57)
2011-10-03 23:39     ` Adam Beneschan
2011-10-04  0:52       ` Yannick Duchêne (Hibou57)
2011-10-04  1:48         ` Yannick Duchêne (Hibou57)
2011-09-25 14:23 ` Robert A Duff
2011-09-25 15:03 ` georg bauhaus
2011-09-26  9:45   ` Natasha Kerensikova
2011-09-26 13:43     ` Robert A Duff
2011-09-26 14:20       ` Dmitry A. Kazakov
2011-09-26 16:15         ` Robert A Duff
2011-09-26 19:30           ` Dmitry A. Kazakov
2011-09-27  0:41             ` Robert A Duff
2011-09-27  8:58               ` Dmitry A. Kazakov
2011-10-04  4:19               ` Yannick Duchêne (Hibou57)
2011-09-27  5:50             ` J-P. Rosen
2011-09-27  7:52               ` Dmitry A. Kazakov
2011-10-04  4:26                 ` Yannick Duchêne (Hibou57)
2011-10-04  7:58                   ` Dmitry A. Kazakov
2011-10-04 15:10                     ` Georg Bauhaus
2011-10-04 15:34                       ` Dmitry A. Kazakov
2011-10-04 15:49                         ` Yannick Duchêne (Hibou57)
2011-10-04 16:04                           ` Dmitry A. Kazakov
2011-10-04 15:44                       ` Yannick Duchêne (Hibou57)
2011-10-04 16:05                         ` Georg Bauhaus
2011-10-04 16:47                           ` Yannick Duchêne (Hibou57)
2011-10-04 15:41                     ` Yannick Duchêne (Hibou57)
2011-09-26 18:59       ` Jeffrey Carter
2011-09-27  0:35         ` Robert A Duff
2011-10-04  4:30         ` Yannick Duchêne (Hibou57)
2011-10-04 18:40           ` Jeffrey Carter
2011-09-26 14:29     ` Georg Bauhaus
2011-09-26 15:31       ` Georg Bauhaus
2011-10-04  4:35       ` Yannick Duchêne (Hibou57)
2011-10-04  4:13     ` Yannick Duchêne (Hibou57)
2011-09-25 17:16 ` Jeffrey Carter
2011-09-25 21:53   ` Robert A Duff
2011-09-26  9:25     ` Georg Bauhaus
2011-09-26 23:00     ` Randy Brukardt
2011-09-27  0:34       ` Robert A Duff

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