comp.lang.ada
 help / color / mirror / Atom feed
From: Natasha Kerensikova <lithiumcat@instinctive.eu>
Subject: Generic instantiation before actual subprogram body
Date: Thu, 4 Dec 2014 08:48:58 +0000 (UTC)
Date: 2014-12-04T08:48:58+00:00	[thread overview]
Message-ID: <slrnm80802.nrc.lithiumcat@nat.rebma.instinctive.eu> (raw)

Hello,

I have fallen into the pattern of refactoring common using generics
instead of cut-and-paste. One of my earliest example of this is
https://github.com/faelys/natools/blob/trunk/src/natools-s_expressions-interpreter_loop.adb

I think it's a good thing, even for only a few tens of lines of code,
mostly for readers who discover the code: explicit common patterns reduce
(I think) the cognitive overhead.
Please enlighten me if I'm wrong on this.

At some early point when I used the pattern, I encountered a GNAT
warning telling that a particular generic instantiation would raise
Program_Error at run-time because the body of actual subprograms in the
instantiation were found later in the source text.

Since then, I always put instantiations after the bodies of the actual
subprograms, even though it makes it a bit awkward.

A lot of time passed, and I'm now feeling the need to refactor a
cut-and-paste-able code structure involved in a recursive cycle.
Recursivity means at some point something has to be called before its
body. This led me to question that instantiation-before-body warning,
so I started experimented, but I couldn't reproduce the warning.

My question is now, in which set of circumstances is it allowed (or
forbidden) to instantiate a generic with a subprogram whose body has not
yet been seen by the compiler?

I'm pretty sure I was using an older GNAT in Ada 2005 mode back then,
could it be something that has changed in Ada 2012?

I tried to read the ARM and then the AARM, on chapters related to
generic instantiation and/or subprogram elaboration (I can't think of
any not-elaboration-related reason to raise Program_Error because of
subprogram body position in the source). I also tried reading GCC
sources, looking for "Program_Error [" and "body seen". However all
these resources are way out of my depth, so I'm asking here.


On a related but almost out-of-topic point, I have always instantiated
generic on a nesting level as shallow as possible. This is due to some
superstitious fear about trampolines and accessibility levels and a few
other nesting-related concept I don't understand.

In the particular case of my alternative-to-cut-and-paste generics, it's
often a generic procedure, whose instances are each called only once, in
a public subprogram whose body consists of almost only the generic
instance call, sometimes with a little bit of argument shuffling or type
adjustments to fit the generic model when the API has a slightly
different logic.

For example I have somewhere code similar to:

package body Whatever is

   procedure Append (...);
   procedure Render_Page_Element (...);

   procedure Render_Page is new Natools.S_Expressions.Interpreter_Loop
     (Output_Accumulator, Page_Type, Render_Page_Element, Append);

   procedure Public_Render
     (Page : in Page_Type;
      Output : in out Output_Accumulator;
      Template : in out Natools.S_Expressions.Lockable.Descriptor'Class) is
   begin
      Render_Page (Template, Output, Page);
   end Public_Render;

end Whatever

Wouldn't it be better in such a case to instantiate the generic inside
Public_Render? That would solve any elaboration issue, and that would
limit the scope of the generic instance to where it is actually use,
which I find is generally a good guideline to follow.
I guess the compiler can easily tell there is no special nesting
mechanism needed, since all actual parameters have a large scope.

Is there any particular rational reason to prefer top-level
instantiation to nested instantiation, or vice versa?


Thanks in advance for your insights,
Natasha

             reply	other threads:[~2014-12-04  8:48 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-04  8:48 Natasha Kerensikova [this message]
2014-12-04  9:31 ` Generic instantiation before actual subprogram body J-P. Rosen
2014-12-04 10:03   ` Natasha Kerensikova
2014-12-04 10:40     ` Georg Bauhaus
2014-12-04 14:12     ` J-P. Rosen
2014-12-04 15:34     ` Robert A Duff
2014-12-04 15:49 ` Robert A Duff
2014-12-04 22:49   ` Randy Brukardt
replies disabled

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