From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on polar.synack.me X-Spam-Level: X-Spam-Status: No, score=-0.9 required=5.0 tests=BAYES_00,FORGED_GMAIL_RCVD, FREEMAIL_FROM autolearn=no autolearn_force=no version=3.4.4 X-Google-Thread: 103376,73175d2d01a1b1dd,start X-Google-NewGroupId: yes X-Google-Attributes: gida07f3367d7,domainid0,public,usenet X-Google-Language: ENGLISH,ASCII-7-bit Received: by 10.68.27.231 with SMTP id w7mr16499312pbg.7.1316941370713; Sun, 25 Sep 2011 02:02:50 -0700 (PDT) Path: lh7ni4512pbb.0!nntp.google.com!news1.google.com!news3.google.com!feeder.news-service.com!eternal-september.org!feeder.eternal-september.org!.POSTED!not-for-mail From: Natasha Kerensikova Newsgroups: comp.lang.ada Subject: subprogram must not be deeper than access type Date: Sun, 25 Sep 2011 09:02:50 +0000 (UTC) Organization: A noiseless patient Spider Message-ID: Mime-Version: 1.0 Injection-Date: Sun, 25 Sep 2011 09:02:50 +0000 (UTC) Injection-Info: mx04.eternal-september.org; posting-host="Mda950WjNwNLAFOE7yJXQw"; logging-data="31166"; mail-complaints-to="abuse@eternal-september.org"; posting-account="U2FsdGVkX18GJ8Lv5l6kJl63t/rRQKrE" User-Agent: slrn/0.9.9p1 (FreeBSD) Cancel-Lock: sha1:U4+aTxN3vv4xHOGzpED1Svs3yAc= Xref: news1.google.com comp.lang.ada:18116 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Date: 2011-09-25T09:02:50+00:00 List-Id: 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