comp.lang.ada
 help / color / mirror / Atom feed
* How is this done?
@ 1994-12-22 17:35 Brian R. Hanson
  1994-12-23 15:26 ` Norman H. Cohen
  0 siblings, 1 reply; 2+ messages in thread
From: Brian R. Hanson @ 1994-12-22 17:35 UTC (permalink / raw)


Given the following package and procedure definitions - 


with Text_Io;
package body Gen_List is 
   procedure View (L: in List) is
   begin
      Text_Io.Put_Line("This is output from view = " & List'Image(L));
   end;
end Gen_List;

generic
package Gen_List is
   type List is new Integer;
   procedure View (L: in List);
end Gen_List;

package body New_List is
   procedure Init (L: out List) is
   begin
      L := 5;
   end;
end New_List;

with Gen_List;
package New_List is
   type List is private;
   procedure View (L: in List);
   procedure Init (L: out List);
private
   package Old_List is new Gen_List;
   type List is new Old_List.List;
end New_list;

with New_List; use New_list;
procedure test is
   A: List;
begin
   View(A);
end test;


What needs to be done to have New_List.View use the View procedure 
that is the result of the type definition for New_List.List?

If I define a body for View in the body of New_List than it overrides
the procedure made available by the type definition - but I have to 
provide a procedure View to get things to compile.

Brian
brh@cray.com




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

* Re: How is this done?
  1994-12-22 17:35 How is this done? Brian R. Hanson
@ 1994-12-23 15:26 ` Norman H. Cohen
  0 siblings, 0 replies; 2+ messages in thread
From: Norman H. Cohen @ 1994-12-23 15:26 UTC (permalink / raw)


In article <1994Dec22.113500.14671@driftwood.cray.com>, brh@cray.com
(Brian R. Hanson) writes: 

|> Given the following package and procedure definitions -
... [example omitted]
|> What needs to be done to have New_List.View use the View procedure
|> that is the result of the type definition for New_List.List?

This is a wicked problem!

Let me rephrase the example more simply.  (By the way, these things are
easier to read if you show the declaration of a package BEFORE its body.)

   generic
   package Template is
      type T1 is ...;
      procedure P (X: in T1);
   end Template;

   with Template; pragma Elaborate (Template);
   package Client is
      type T2 is private;
      procedure P (X: in T2);
   private
      package Instance is new Template;
         -- There is a procedure Instance.P with an Instance.T1 parameter
      type T2 is new Instance.T1;
         -- A procedure P with a T2 parameter is inherited from Instance.T1
         --   and implicitly declared here.
   end Client;

Brian wants Client.P to behave like Instance.P.  He observes that if he
doesn't provide a body for Client.P he gets a compile-time error, but if
he does, "the body overrides" the inherited version.

The declaration of P in the Client package declaration obligates the
Client package body (in the absence of an Interface or Import pragma) to
provide an implementation.  This implementation must be a subprogram body
in Ada 83; it is also allowed to be a renaming declaration in Ada 95.

However, there are two distinct declarations immediately within package
Client for a procedure named P.  One is the explicit declaration
following the private-type declaration.  The other is the implicit
declaration of the inherited procedure immediately following the
derived-type declaration.  Because both declarations are for a procedure
with one parameter, of type T2, the declarations are "homographs".  Two
homographs are not allowed in the same "declarative region" unless at
leat one of them is implicit.  (In this case the the declaration and body
of Client together form a single declarative region.)  Given an explicit
and implicit homograph in the same declarative region, the explicit one
hides the implicit one, starting at the point of the explicit
declaration.  In this case, the version of P inherited from Instance.T1
is "born hidden".  It is theoretically there, but there is no way to
refer to it.

Thus it is not the body of Client.P that overrides the inherited P; it is
the declaration of P in the visible part of Client that does so.

The most straightforward solution is to use different names for the
operation provided by Client and the operation provided by instances of
Template: 

   with Template; pragma Elaborate (Template);
   package Client is
      type T2 is private;
      procedure Q (X: in T2);  -- previously named P
   private
      package Instance is new Template;
         -- There is a procedure Instance.P with an Instance.T1 parameter
      type T2 is new Instance.T1;
         -- A procedure P with a T2 parameter is inherited from Instance.T1
         --   and implicitly declared here.
   end Client;

   package body Client is

      procedure Q (X: in T2) is
      begin
         P(X);  -- calls the procedure inherited from Instance.T1
      end Q;

      -- Or, in Ada 95, simply
      --    procedure Q(X: in T2) renames P;

   end Client;

If there is a requirement to use the same name in Template and Client,
you can do this: 

   with Template; pragma Elaborate(Template);
   package Intermediate is
      package Instance is new Template;
      type T_1_Point_5 is new Instance.T1;
      procedure Q (X: in T2) renames P;
         -- Provide an alternative name that won't get hidden.
   end Intermediate;

   with Intermediate;
   package Client is
      type T2 is private;
      procedure P (X: in T2);
   private
      type T2 is new Intermediate.T_1_Point_5;
         -- Procedures P and Q, each with a T2 parameter, are inherited
         --   from Intermediate.T_1_Point_5  and implicitly declared here.
         --   The declaration of P is hidden as before, but the declaration
         --   of Q is not.
   end Client;

   package body Client is

      procedure P (X: in T2) is
      begin
         Q (X);
      end P;

      -- Or, in Ada 95, simply
      --    procedure P (X: in T2) renames Q;

   end Client;

(Package Intermediate, type T_1_Point_5, and the view of P named Q are
part of the implementation of Client, not meant for use outside of
Client.  In Ada 95, package Client could be made a visible child, and
package Intermediate a private child, of an empty parent package, say
Root. Root.Intermediate and the facilities it provides to Root.Client
would then be hidden from the rest of the program.)

Other alternatives include instantiating Template and deriving T2 from
Instance.T1 in the VISIBLE part of Client (so that P is not declared
explicitly in Client, but the implicit declaration of the inherited
version is available to all users of Client); or, in Ada 95, evaluating
whether Template can be turned into a nongeneric package providing an
abstract tagged type, and replacing instantiations by extensions of this
type.

--
Norman H. Cohen    ncohen@watson.ibm.com



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

end of thread, other threads:[~1994-12-23 15:26 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1994-12-22 17:35 How is this done? Brian R. Hanson
1994-12-23 15:26 ` Norman H. Cohen

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