comp.lang.ada
 help / color / mirror / Atom feed
From: "David C. Hoos, Sr." <david.c.hoos.sr@ada95.com>
Subject: Re: Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html?
Date: 1999/04/07
Date: 1999-04-07T00:00:00+00:00	[thread overview]
Message-ID: <5VxQ6WNg#GA.143@pet.hiwaay.net> (raw)
In-Reply-To: 01be80c2$114e0890$c24d3a8b@m04w0588


Daniel Wengelin wrote in message <01be80c2$114e0890$c24d3a8b@m04w0588>...
>
>
>When looking around for some infomration about OOP I came across the
>article http://www.adahome.com/articles/1998-02/ar_lessons95.html.
>
<large snip>

>I gave the code a try with Gnat 3.11 as follows.
>
>generic
>   type Item_T is private;
>package List is
>   type Node;
>   type Object is access Node;
>   type Node is record
>      I : Item_T;
>      Next:Object;
>   end record;
>
>   type Action_Proc is access procedure
>     (I : in out Item_T);
>   procedure Iterate
>     (The_Action : Action_Proc;
>      Through_List : Object);
>end List;
>
>---------------------------
>package body List is
>   procedure Iterate
>     (The_Action : Action_Proc;
>      Through_List : Object)
>   is
>      Current : Object := Through_List;
>   begin
>      while Current /= null loop
>         The_Action(Current.I);
>         Current := Current.Next;
>      end loop;
>   end Iterate;
>end List;
>
>------------------------
>
>procedure List_Test is
>
>   procedure Print (C: in out Character) is
>   begin
>      Ada.Text_Io.Put(C);
>      Ada.Text_Io.New_Line;
>   end Print;
>   package C_List is new List(Character);
>
>   The_List : C_List.Object := null;
>begin
>   for I in Character range 'a' .. 'e' loop
>      The_List := new C_List.Node'(I, The_List);
>   end loop;
>
>   C_List.Iterate (Print'Access, The_List);
>end List_Test;
>
>The above source compiled and ran without any problems. So, did I
>misunderstand or is Gnat wrong or is the article in AdaHome wrong?
>

Well, you must have an amazing version of gnat-3.11, for your code
won't compile either without the required context clauses for
Ada.Text_IO, and List in the List_Test source file ;).

But, seriously, I am glad to say Jean-Marie Dautelle is incorrect
in the article you cited.

Indeed I have used access to subprograms many times in multi-tasking
programs.  The basic rule is that accesses to subprograms must
not have a lifetime greater than that of the subprogram.

So, in your example, even though the procedure Print only exists
during the execution of procedure List_Test, there is no problem
because the lifetime of Print cannot be less than that of the
access type C_List.Action_Proc;

Frequently, all this limitation means is that the subprogram must
be declared at library level -- i.e. such that the lifetime of
the subprogram is the same as that of the main program.

For example, if you make this small change to your code (leaving
the generic List package unchanged, the program will not compile:

----
with List;
package C_List is new List(Character);
----
with Ada.Text_IO;
with C_List;
procedure List_Test is
   procedure Print (C: in out Character) is
   begin
      Ada.Text_IO.Put(C);
      Ada.Text_IO.New_Line;
   end Print;
   The_List : C_List.Object := null;
begin
   for I in Character range 'a' .. 'e' loop
      The_List := new C_List.Node'(I, The_List);
   end loop;

   C_List.Iterate (Print'Access, The_List);
end List_Test;
----

In this case, the access type C_List.Action_Proc could have a
lifetime greater than that of the subprogram Print.  When gcc
compiles List_Test, it has no way of knowing that List_Test
is the main program, so the compilation fails.  As the RM
puts it, the subprogram access level is deeper than that of
the access type, which is not allowed.

But what if the generic instantiation C_List is to be used
by more than one compilation unit, and therefore must be
declared at library level? Again, another small change makes
things well again.

with List;
package C_List is new List(Character);
----
with Ada.Text_IO;
procedure Print (C: in out Character) is
begin
   Ada.Text_IO.Put(C);
   Ada.Text_IO.New_Line;
end Print;
----
with C_List;
with Print;
procedure List_Test is
   The_List : C_List.Object := null;
begin
   for I in Character range 'a' .. 'e' loop
      The_List := new C_List.Node'(I, The_List);
   end loop;

   C_List.Iterate (Print'Access, The_List);
end List_Test;
----

Now, once again, the lifetime of Print is at least as long
as that of the access type C_List.Action_Proc.





  parent reply	other threads:[~1999-04-07  0:00 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-04-07  0:00 Who is right? Gnat or http://www.adahome.com/articles/1998-02/ar_lessons95.html? Daniel Wengelin
1999-04-07  0:00 ` Robert Dewar
1999-04-07  0:00 ` David C. Hoos, Sr. [this message]
1999-04-07  0:00   ` Daniel Wengelin
1999-04-07  0:00 ` Tucker Taft
replies disabled

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