-- CA11012.A
--
--                             Grant of Unlimited Rights
--
--     Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
--     F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained 
--     unlimited rights in the software and documentation contained herein.
--     Unlimited rights are defined in DFAR 252.227-7013(a)(19).  By making 
--     this public release, the Government intends to confer upon all 
--     recipients unlimited rights  equal to those held by the Government.  
--     These rights include rights to use, duplicate, release or disclose the 
--     released technical data and computer software in whole or in part, in 
--     any manner and for any purpose whatsoever, and to have or permit others 
--     to do so.
--
--                                    DISCLAIMER
--
--     ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
--     DISCLOSED ARE AS IS.  THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED 
--     WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
--     SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE 
--     OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
--     PARTICULAR PURPOSE OF SAID MATERIAL.
--*
--
-- OBJECTIVE:
--      Check that a child package of a library level instantiation
--      of a generic can be the instantiation of a child package of
--      the generic. Check that the child instance can use its parent's
--      declarations and operations, including a formal type of the parent. 
--      
-- TEST DESCRIPTION:
--      Declare a generic package which simulates an integer complex 
--      abstraction.  Declare a generic child package of this package 
--      which defines additional complex operations. 
--
--      Instantiate the first generic package, then instantiate the child 
--      generic package as a child unit of the first instance.  In the main
--      program, check that the operations in both instances perform as 
--      expected.
--
--
-- CHANGE HISTORY:
--      06 Dec 94   SAIC    ACVC 2.0
--      21 Dec 94   SAIC    Corrected visibility errors for literals
--      27 Feb 97   PWB.CTA Added elaboration pragma at package CA11012_3
--!
generic               -- Complex number abstraction.
   type Int_Type is range <>;
package CA11012_0 is
 
   -- Simulate a generic complex number support package. Complex numbers
   -- are treated as coordinates in the Cartesian plane.
   type Complex_Type is private;
   Zero : constant Complex_Type;                      -- Real number (0,0).
   function Complex (Real, Imag : Int_Type)           -- Create a complex
     return Complex_Type;                             -- number.
   function "-" (Right : Complex_Type)                -- Invert a complex
     return Complex_Type;                             -- number.
   function "+" (Left, Right : Complex_Type)          -- Add two complex
     return Complex_Type;                             -- numbers.
private
   type Complex_Type is record
      Real : Int_Type;
      Imag : Int_Type;
   end record;
   Zero : constant Complex_Type := (Real => 0, Imag => 0);
end CA11012_0;
     --==================================================================--
package body CA11012_0 is
   function Complex (Real, Imag : Int_Type) return Complex_Type is
   begin
      return (Real, Imag);
   end Complex;
   ---------------------------------------------------------------
   function "-" (Right : Complex_Type) return Complex_Type is
   begin
      return (-Right.Real, -Right.Imag);
   end "-";
   ---------------------------------------------------------------
   function "+" (Left, Right : Complex_Type) return Complex_Type is
   begin
      return ( (Left.Real + Right.Real, Left.Imag + Right.Imag) );
   end "+";
end CA11012_0;
     --==================================================================--
-- Generic child of complex number package.  Child must be generic since 
-- parent is generic. 
generic               -- Complex additional operations
package CA11012_0.CA11012_1 is
 
   -- More operations on complex number. This child adds a layer of
   -- functionality to the parent generic.
   function Real_Part (Complex_No : Complex_Type)
     return Int_Type;
   function Imag_Part (Complex_No : Complex_Type)
     return Int_Type;
   function "*" (Factor : Int_Type; 
                 C      : Complex_Type) return Complex_Type;
   function Vector_Magnitude (Complex_No : Complex_Type)
     return Int_Type;
end CA11012_0.CA11012_1;
     --==================================================================--
package body CA11012_0.CA11012_1 is
   function Real_Part (Complex_No : Complex_Type) return Int_Type is
   begin
      return (Complex_No.Real);
   end Real_Part;
   ---------------------------------------------------------------
   function Imag_Part (Complex_No : Complex_Type) return Int_Type is
   begin
      return (Complex_No.Imag);
   end Imag_Part;
   ---------------------------------------------------------------
   function "*" (Factor : Int_Type; 
                 C      : Complex_Type) return Complex_Type is
      Result : Complex_Type := Zero;   -- Zero is declared in parent,
                                       -- Complex_Number
   begin
      for I in 1 .. abs (Factor) loop
         Result := Result + C;         -- Complex_Number "+"
      end loop;
      if Factor < 0 then
         Result := - Result;           -- Complex_Number "-"
      end if;
      return Result;
   end "*";
   ---------------------------------------------------------------
   function Vector_Magnitude (Complex_No : Complex_Type)
     return Int_Type is                -- Not a real vector magnitude.
   begin
      return (Complex_No.Real + Complex_No.Imag);
   end Vector_Magnitude;  
end CA11012_0.CA11012_1;
     --==================================================================--
package CA11012_2 is
   subtype My_Integer is integer range -100 .. 100;
   -- ... Various other types used by the application.
end CA11012_2;
-- No body for CA11012_2;
     --==================================================================--
-- Declare instances of the generic complex packages for integer type.  
-- The instance of the child must itself be declared as a child of the 
-- instance of the parent.
with CA11012_0;                        -- Complex number abstraction
with CA11012_2;                        -- Package containing integer type
pragma Elaborate (CA11012_0);
package CA11012_3 is new CA11012_0 (Int_Type => CA11012_2.My_Integer);
with CA11012_0.CA11012_1;              -- Complex additional operations
with CA11012_3;
package CA11012_3.CA11012_4 is new CA11012_3.CA11012_1;
     --==================================================================--
with CA11012_2;                -- Package containing integer type
with CA11012_3.CA11012_4;      -- Complex abstraction + additional operations
with Report;
procedure CA11012 is
   package My_Complex_Pkg renames CA11012_3;
   package My_Complex_Operation renames CA11012_3.CA11012_4;
   use My_Complex_Pkg,                                -- All user-defined
       My_Complex_Operation;                          -- operators directly
                                                      -- visible.
   Complex_One, Complex_Two : Complex_Type;
begin
   Report.Test ("CA11012", "Check that child instance can use its parent's "  &
                           "declarations and operations, including a formal " &
                           "type of the parent");
   Correct_Range_Test:
   declare
      My_Literal  : CA11012_2.My_Integer := -3;
   begin
      Complex_One := Complex (-4, 7);          -- Operation from the generic 
                                               -- parent package.
      Complex_Two := My_Literal * Complex_One; -- Operation from the generic 
                                               -- child package.
      if Real_Part (Complex_Two) /= 12         -- Operation from the generic 
        or Imag_Part (Complex_Two) /= -21      -- child package.
          then
             Report.Failed ("Incorrect results from complex operation");
      end if;
   end Correct_Range_Test;
   ---------------------------------------------------------------
   Out_Of_Range_Test:
   declare
      My_Vector : CA11012_2.My_Integer;
   begin
      Complex_One := Complex (70, 70);         -- Operation from the generic 
                                               -- parent package.
      My_Vector := Vector_Magnitude (Complex_One);         
                     -- Operation from the generic child package.
      Report.Failed ("Exception not raised in child package");
   exception
      when Constraint_Error =>
        Report.Comment ("Exception is raised as expected");
      when others           =>
        Report.Failed ("Others exception is raised");
   end Out_Of_Range_Test;
   Report.Result;
end CA11012;