comp.lang.ada
 help / color / mirror / Atom feed
From: ncohen@watson.ibm.com (Norman H. Cohen)
Subject: Re: cross linking packages
Date: 2 Dec 1994 14:30:52 GMT
Date: 1994-12-02T14:30:52+00:00	[thread overview]
Message-ID: <3bnb2s$1ej1@watnews1.watson.ibm.com> (raw)
In-Reply-To: 3bj0br$mri@network.ucsd.edu

In article <3bj0br$mri@network.ucsd.edu>, mbk@inls1.ucsd.edu
(Matt Kennel) writes: 

|> Can somebody answer this question: 
|>
|>   Why were cyclical dependencies among types defined illegal?
|>
|> (I.e. type A defines features that use type B, and type B defines
|>  features that use type A.)
...
|>
|> It apparently works fine when they are in the same package.
|> Thus supposing you put two types each in their own package, both inside
|> an outer package.
|>
|> Do the mutual dependencies now work fine because they are both inside
|> one package, the outer one?

It is straightforward to define different types in a mutually recursive
data structure in two or more packages.  The following works in Ada 83
or Ada 9X: 

   package A_Package is
      type A is private;
      ...
   private
      type A_Node;  -- incomplete type declaration, completed in body
      type A is access A_Node;
   end A_Package;

   package B_Package is
      type B is private;
      ...
   private
      type B_Node;  -- incomplete type declaration, completed in body
      type B is access B_Node;
   end B_Package;

  with B_Package;
  package body A_Package is
     type A_Node is
        record
           ...
           B_Part: B_Package.B;
           ...
        end record;
     ...
  end A_Package;

  with A_Package;
  package body B_Package is
     type B_Node is
        record
           ...
           A_Part: A_Package.A;
           ...
        end record;
     ...
  end B_Package;

In this case both package bodies depend on both package declarations, but
the package declarations do not depend on each other, so there is no
circularity.

The difficulty the original questioner had was not in defining a mutually
recursive DATA STRUCTURE, but mutually recursive INTERFACES: 

with B_Package;                     |with A_Package;
package A_Package is                |package B_Package is
   type A is ...;                   |   type B is ...;
   procedure Op                     |   procedure Op
      (...; X: in B_Package.B; ...);|      (...; X: in A_Package.A; ...);
   ...                              |   ...
end A_Package;                      |end B_Package;

There is no way to do this without making each of the package
declarations dependent on the other.  In Ada 9X, a way out is to make A
and B tagged types derived from abstract tagged types declared elsewhere,
and to replace references to A and B in each others' interfaces by
references to the parent types' classwide types, thus eliminating the
circular dependences between the A_Package declaration and the B_Package
declaration.

The circularity presents a difficulty because Ada programs are compiled
and checked for consistency incrementally, a compilation unit at a time.
It was a principle design goal of Ada to facilitate the development of
huge programs in this manner, with each compilation unit checked, when it
is compiled, for consistency with all units whose facilities it uses.
This requires that units be compiled in some order such that all
declarations of facilties to be provided by a unit have been compiled
before all uses of those facilities.  It might be possible, in theory, to
rewrite the language rules to allow the mutually dependent declarations
of A_Package and B_Package by deferring all consistency checks and code
generation until all required packages had been compiled.  However, this
would violate the requirement for incremental recompilation and
rechecking of small pieces of a program and return us to the era of "big
bang" integration of modules compiled in isolation from each other.

Allowing ciruclarity in with clauses would make it possible for other
embarassing circularities to arise, and some way would have to be found
to deal with those: 

with B_Package;                     |with A_Package;
package A_Package is                |package B_Package is
   type A is                        |   type B is
      array (1 .. B_Package.B'Last) |      array (1 .. A_Package.A'Last)
         of Integer;                |         of Integer;
   ...                              |   ...
end A_Package;                      |end B_Package;

|> After all in a statically typed langauge like Ada, all variables
|> must be bound to types statically at compile time, so there
|> should be no ambiguity in "elaboration order" as there is no
|> run-time execution that must take place to bind variables
|> to types.

The type of a variable is indeed a compile-time property, but the size of
a type (and thus the code that must be generated to manipulate it
efficiently) is not.  Type declarations are "elaborated" (executed) at
run time.  Given a function Next_Number_In_Input_File that reads and
returns a value from an input file, for example, a type can be declared
as

   type T is array (1 .. Next_Number_In_Input_File) of Integer;

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



  reply	other threads:[~1994-12-02 14:30 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1994-11-28 12:56 cross linking packages Rene Burema
1994-11-29 18:28 ` Norman H. Cohen
1994-11-29 22:07 ` Robert Dewar
1994-11-30 16:33   ` David Weller
1994-12-01 13:44     ` Robert I. Eachus
1994-11-30 23:03   ` Matt Kennel
1994-12-02 14:30     ` Norman H. Cohen [this message]
1994-12-05 20:57     ` Elaboration order [was: cross linking packages] John Volan
1994-12-06 16:11       ` Robert Dewar
1994-12-05 13:30 ` cross linking packages John Volan
  -- strict thread matches above, loose matches on Subject: below --
1994-12-06 16:34 Bob Wells #402
replies disabled

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