comp.lang.ada
 help / color / mirror / Atom feed
* Curiosity in generic package instantiation
@ 2014-08-19 22:26 GianLuigi Piacentini
  2014-08-19 23:16 ` Adam Beneschan
  2014-08-20  7:18 ` Björn Lundin
  0 siblings, 2 replies; 6+ messages in thread
From: GianLuigi Piacentini @ 2014-08-19 22:26 UTC (permalink / raw)


Hi all,

pardon if using not the exact terminology (too old to learn ADA intricacies, 
whish had done it back in the '80-'90 when I was active programmer, but then 
in Italy buzzword was c/c++ m$oft version, and VB), I noticed the following 
excerpt in a previous thread:

...
procedure Test_List is
    type Example_Type is record
      A :Integer := 0;
      B: Integer := 0;
    end record;

...

  declare
    Data : Example_Type;
    package Example_Pkg is new
Ada.Containers.Doubly_Linked_Lists(Example_Type);
    List : Example_Pkg.List;

if I understand well, this means that the Ada.Containers.Doubly_Linked_Lists 
package is instantiated using Example_Type, and the instantiated list name 
is Example_Pkg.List.

Is this done by text substitution at source/intermediate code level 
(something like the C preprocessor), albeit in an user-transparent (=better) 
way, or is it obtained by some property of the list elements, able to store 
whatever is thrown at them, even elements of different type in the same 
list?

My 1st guess looking at the code is sort of compiler-integrated 
preprocessing.

Just curious.

Thanks in advance.

Gigi


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

* Re: Curiosity in generic package instantiation
  2014-08-19 22:26 Curiosity in generic package instantiation GianLuigi Piacentini
@ 2014-08-19 23:16 ` Adam Beneschan
  2014-08-20  8:56   ` Mark Lorenzen
  2014-08-21 22:39   ` Randy Brukardt
  2014-08-20  7:18 ` Björn Lundin
  1 sibling, 2 replies; 6+ messages in thread
From: Adam Beneschan @ 2014-08-19 23:16 UTC (permalink / raw)


On Tuesday, August 19, 2014 3:26:01 PM UTC-7, GianLuigi Piacentini wrote:
> Hi all,
> 
> pardon if using not the exact terminology (too old to learn ADA intricacies, 
> whish had done it back in the '80-'90 when I was active programmer, but then 
> in Italy buzzword was c/c++ m$oft version, and VB), I noticed the following 
> excerpt in a previous thread:
> 
> ...
> 
> procedure Test_List is
>     type Example_Type is record
>       A :Integer := 0;
>       B: Integer := 0;
>     end record;
> 
> ...
> 
>   declare
>     Data : Example_Type;
>     package Example_Pkg is new
> Ada.Containers.Doubly_Linked_Lists(Example_Type);
>     List : Example_Pkg.List;
> 
> if I understand well, this means that the Ada.Containers.Doubly_Linked_Lists 
> package is instantiated using Example_Type, and the instantiated list name 
> is Example_Pkg.List.
> 
> Is this done by text substitution at source/intermediate code level 
> (something like the C preprocessor), albeit in an user-transparent (=better) 
> way, or is it obtained by some property of the list elements, able to store 
> whatever is thrown at them, even elements of different type in the same 
> list?
> 
> My 1st guess looking at the code is sort of compiler-integrated 
> preprocessing.
> 
> Just curious.

An implementation can do either.  Suppose you instantiate Ada.Containers.Doubly_Linked_Lists with multiple types in the same program:

    package Example_Pkg is new Ada.Containers.Doubly_Linked_List(Example_Type);
    package Another_Pkg is new Ada.Containers.Doubly_Linked_List(Another_Type);
    package A_Third_Pkg is new Ada.Containers.Doubly_Linked_List(Type_3);

If you compile with GNAT, you'll get three copies of the Doubly_Linked_List code, with each copy set up to work on a different type.  If you compile with Janus Ada, you will get only one copy of the code.  I'm not entirely sure what the code looks like, but probably when the subprograms in the instantiation are called, they will be given a parameter that contains some information needed about each type, such as the size of the type, so that the code in the instantiation will know what to do when copying objects of the type around.  I'm assuming this approach takes less code space but performs a little slower.

The language is designed to support both approaches, and the designers are careful to make sure that both approaches are possible when new language features are added.

The language rules about generic make it so that instantiating a generic is *almost* the same as text substitution, but not quite.  The names and operators in generic code normally mean what they mean when the generic is *compiled*, not when it's instantiated (with some exceptions).  So if you say

    generic
        type FLOAT_TYPE is digits <>;  -- generic formal floating-point type
    package Some_Package is ...

and in the body, you use X + Y on two FLOAT_TYPE's, you will always get the standard meaning of "+" even if you redefine "+" to mean something else on some user-defined floating-point type (a bad idea anyway) and instantiate your package with that type.  If it were a straight text substitution, you'd get the redefined "+", but that isn't how Ada works.  The actual rules are complicated and there are some nuances, though.  But it shouldn't be an issue, until you start writing more complex generics.

                                -- Adam


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

* Re: Curiosity in generic package instantiation
  2014-08-19 22:26 Curiosity in generic package instantiation GianLuigi Piacentini
  2014-08-19 23:16 ` Adam Beneschan
@ 2014-08-20  7:18 ` Björn Lundin
  1 sibling, 0 replies; 6+ messages in thread
From: Björn Lundin @ 2014-08-20  7:18 UTC (permalink / raw)


On 2014-08-20 00:26, GianLuigi Piacentini wrote:
> if I understand well, this means that the Ada.Containers.Doubly_Linked_Lists 
> package is instantiated using Example_Type, and the instantiated list name 
> is Example_Pkg.List.

Almost, but not quite.
The list is called 'List' and is of _type_ Example_Pkg.List

I am one of hem who prefers tucking '_Type' in the end of type names
just to avoid this sort of confusion.
So if I wrote the package, the type would have been called

Example_Pkg.List_Type


--
Björn

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

* Re: Curiosity in generic package instantiation
  2014-08-19 23:16 ` Adam Beneschan
@ 2014-08-20  8:56   ` Mark Lorenzen
  2014-08-21 22:32     ` Randy Brukardt
  2014-08-21 22:39   ` Randy Brukardt
  1 sibling, 1 reply; 6+ messages in thread
From: Mark Lorenzen @ 2014-08-20  8:56 UTC (permalink / raw)


On Wednesday, August 20, 2014 1:16:48 AM UTC+2, Adam Beneschan wrote:
> 
> If you compile with GNAT, you'll get three copies of the Doubly_Linked_List code, with each copy set up to work on a different type.  If you compile with 

Yes although I'm quite certain that the GNAT container library is written such that only the necessary code copied when instantiated and that code then calls shared (non-instantiated) code.

Regards,

Mark L

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

* Re: Curiosity in generic package instantiation
  2014-08-20  8:56   ` Mark Lorenzen
@ 2014-08-21 22:32     ` Randy Brukardt
  0 siblings, 0 replies; 6+ messages in thread
From: Randy Brukardt @ 2014-08-21 22:32 UTC (permalink / raw)


"Mark Lorenzen" <mark.lorenzen@gmail.com> wrote in message 
news:dc2f1578-3fb5-468d-bc26-35dd52da577e@googlegroups.com...
> On Wednesday, August 20, 2014 1:16:48 AM UTC+2, Adam Beneschan wrote:
>>
>> If you compile with GNAT, you'll get three copies of the 
>> Doubly_Linked_List code,
>> with each copy set up to work on a different type.  If you compile with
>
> Yes although I'm quite certain that the GNAT container library is written 
> such that only
> the necessary code copied when instantiated and that code then calls 
> shared (non-instantiated) code.

It's likely that there isn't much such code though, because almost 
everything in a container depends upon the element type, which is different 
for each instantiation. (It's the same reason that having a general 
container interface doesn't make much sense.) From what I've heard about the 
current GNAT implementation, it doesn't do much internal sharing.

                             Randy.




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

* Re: Curiosity in generic package instantiation
  2014-08-19 23:16 ` Adam Beneschan
  2014-08-20  8:56   ` Mark Lorenzen
@ 2014-08-21 22:39   ` Randy Brukardt
  1 sibling, 0 replies; 6+ messages in thread
From: Randy Brukardt @ 2014-08-21 22:39 UTC (permalink / raw)


"Adam Beneschan" <adambeneschan@gmail.com> wrote in message 
news:f9998a20-46fd-492a-b8a3-02105f728e82@googlegroups.com...
...
>An implementation can do either.  Suppose you instantiate 
>Ada.Containers.Doubly_Linked_Lists
> with multiple types in the same program:
>
>    package Example_Pkg is new 
> Ada.Containers.Doubly_Linked_List(Example_Type);
>    package Another_Pkg is new 
> Ada.Containers.Doubly_Linked_List(Another_Type);
>    package A_Third_Pkg is new Ada.Containers.Doubly_Linked_List(Type_3);
>
> If you compile with GNAT, you'll get three copies of the 
> Doubly_Linked_List code, with
> each copy set up to work on a different type.  If you compile with Janus 
> Ada, you will get
> only one copy of the code.  I'm not entirely sure what the code looks 
> like, but probably
> when the subprograms in the instantiation are called, they will be given a 
> parameter that
> contains some information needed about each type, such as the size of the 
> type, so that
> the code in the instantiation will know what to do when copying objects of 
> the type
> around.  I'm assuming this approach takes less code space but performs a 
> little slower.

The run-time cost (if any) depends mainly on the type of formal parameter. 
For formal private types, the code is almost the same as it would have been 
anyway (assignments and initializations being done about the same as they 
would have anyway, especially if the actual type is some sort of record). 
(There's a small cost for declared objects as they need an extra level of 
indirection.) Similarly, the various formal scalar types are not much 
impacted. OTOH, some of the lesser used formal parameters have a larger cost 
(in code and space).

Our original plan was to use automatic inlining to reduce these costs (it's 
a lot easier to unshare code that was compiled to be shared than it is to 
share code that was compiled separately -- we did the latter for our Z-80 
CP/M compilers, but it didn't work at all on the 8086 processors). We never 
got around to implementing that (in part because it required larger hosts 
than were common back in the day, and now there is a long list of other 
things that are more important), so it's hard to say how well that would 
have worked.

                                                 Randy.


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

end of thread, other threads:[~2014-08-21 22:39 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-08-19 22:26 Curiosity in generic package instantiation GianLuigi Piacentini
2014-08-19 23:16 ` Adam Beneschan
2014-08-20  8:56   ` Mark Lorenzen
2014-08-21 22:32     ` Randy Brukardt
2014-08-21 22:39   ` Randy Brukardt
2014-08-20  7:18 ` Björn Lundin

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