------------------------------------------------------------------------------
--                                                                          --
--                   ASIS-for-GNAT INTERFACE COMPONENTS                     --
--                                                                          --
--                A S I S . D A T A _ D E C O M P O S I T I O N             --
--                                                                          --
--                                 S p e c                                  --
--                                                                          --
--            Copyright (C) 1995-2013, Free Software Foundation, Inc.       --
--                                                                          --
-- This   specification  is  derived   from  the  Ada   Semantic  Interface --
-- Specification Standard (ISO/IEC 15291) for use with GNAT.  The copyright --
-- notice above, and the license provisions that follow apply solely to the --
--  contents of the part following the private keyword.                     --
--                                                                          --
-- ASIS-for-GNAT is free software; you can redistribute it and/or modify it --
-- under terms of the  GNU General Public License  as published by the Free --
-- Software  Foundation;  either version 3,  or (at your option)  any later --
-- version.  ASIS-for-GNAT  is  distributed  in  the  hope  that it will be --
-- useful,  but  WITHOUT ANY WARRANTY; without even the implied warranty of --
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.                     --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
--                                                                          --
-- You should have  received  a copy of the  GNU General Public License and --
-- a copy of the  GCC Runtime Library Exception  distributed with GNAT; see --
-- the files COPYING3 and COPYING.RUNTIME respectively.  If not, see        --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
-- ASIS-for-GNAT was originally developed  by the ASIS-for-GNAT team at the --
-- Software  Engineering  Laboratory  of  the Swiss  Federal  Institute  of --
-- Technology (LGL-EPFL) in Lausanne,  Switzerland, in cooperation with the --
-- Scientific  Research  Computer  Center of  Moscow State University (SRCC --
-- MSU), Russia,  with funding partially provided  by grants from the Swiss --
-- National  Science  Foundation  and  the  Swiss  Academy  of  Engineering --
-- Sciences. ASIS-for-GNAT is now maintained by AdaCore                     --
-- (http://www.adacore.com).                                                --
--                                                                          --
------------------------------------------------------------------------------

------------------------------------------------------------------------------
--  22   package Asis.Data_Decomposition (optional)
------------------------------------------------------------------------------
------------------------------------------------------------------------------
with Repinfo; use Repinfo;

package Asis.Data_Decomposition is
------------------------------------------------------------------------------
------------------------------------------------------------------------------
--  Asis.Data_Decomposition
--
--  This package is optional.
--
--  Operations to decompose data values using the ASIS type information and a
--  Portable_Data stream, representing a data value of that type.
--
--  An application can write data, using the
--  Asis.Data_Decomposition.Portable_Transfer package to an external medium
--  for later retrieval by another application.  The second application reads
--  that data and then uses this package to convert that data into useful
--  information.  Simple discrete scalar types can be converted directly into
--  useful information.  Composite types, such as records and arrays,
--  shall first be broken into their various discriminants and components.
--
--  A data stream representing a record value can be decomposed into a group
--  of discriminant and component data streams by extracting those streams
--  from the record's data stream.  This extraction is performed by applying
--  any of the Record_Components which describe the discriminants and
--  components of the record type.  Each discriminant and each component of a
--  record type is described by a Record_Component value.  Each value
--  encapsulates the information needed, by the implementation, to efficiently
--  extract the associated field from a data stream representing a record
--  value of the correct type.
--
--  A data stream representing an array value can be decomposed into a group
--  of component data streams by extracting those streams from the array's
--  data stream.  This extraction is performed by applying the single
--  Array_Component which describes the components of the array type.  One
--  Array_Component value is used to describe all array components.  The value
--  encapsulates the information needed, by the implementation, to efficiently
--  extract any of the array components.
--
--  Assumptions and Limitations of this Interface:
--
--  a) The data stream is appropriate for the ASIS host machine.  For example,
--     the implementation of this interface will not need to worry about
--     byte flipping or reordering of bits caused by movement of data between
--     machine architectures.
--
--  b) Records, arrays, and their components may be packed.
--
--  c) Records, array components, enumerations, and scalar types may have
--     representation and length clauses applied to them.  This includes scalar
--     types used as record discriminants and array indices.
--
--  d) This specification supports two of the three type models discussed
--     below.  Models A and B are supported.  Model C is not supported.
--
--     1) Simple "static" types contain no variants, have a single fixed 'Size,
--        and all components and attributes are themselves static and/or fully
--        constrained.  The size and position for any component of the type
--        can be determined without regard to constraints.  For example:
--
--           type Static_Record is
--               record
--                   F1, F2 : Natural;
--                   C1     : Wide_Character;
--                   A1     : Wide_String (1..5);
--               end record;
--
--           type Static_Discriminated (X : Boolean) is
--               record
--                   F1, F2 : Natural;
--                   C1     : Wide_Character;
--               end record;
--
--           type Static_Array   is array (Integer range 1 .. 100) of Boolean;
--           type Static_Enum    is (One, Two, Three);
--           type Static_Integer is range 1 .. 512;
--           type Static_Float   is digits 15 range -100.0 .. 100.0;
--           type Static_Fixed   is delta 0.1 range -100.0 .. 100.0;
--
--     2) Simple "dynamic" types contain one or more components or attributes
--        whose size, position, or value depends on the value of one or more
--        constraints computed at execution time.  This means that the size,
--        position, or number of components within the data type cannot be
--        determined without reference to constraint values.
--
--        Records containing components, whose size depends on discriminants
--        of the record, can be handled because the discriminants for a record
--        value are fully specified by the data stream form of the record
--        value. For example:
--
--            type Dynamic_Length (Length : Natural) is
--                record
--                    S1 : Wide_String (1 .. Length);
--                end record;
--
--            type Dynamic_Variant (When : Boolean) is
--                record
--                    case When is
--                        when True =>
--                            C1 : Wide_Character;
--                        when False =>
--                            null;
--                    end case;
--                end record;
--
--        Arrays with an unconstrained subtype, whose 'Length, 'First, and
--        'Last depend on dynamic index constraints, can be handled because
--        these attributes can be queried and stored when the data stream is
--        written. For example:
--
--             I : Integer := Some_Function;
--             type Dynamic_Array is
--                 array (Integer range I .. I + 10) of Boolean;
--
--             type Heap_Array   is array (Integer range <>) of Boolean;
--             type Access_Array is access Heap_Array;
--             X : Access_Array := new Heap_Array (1 .. 100);
--
--     3) Complex, externally "discriminated" records, contain one or more
--        components whose size or position depends on the value of one or
--        more non-static external values (values not stored within instances
--        of the type) at execution time.  The size for a value of the type
--        cannot be determined without reference to these external values,
--        whose runtime values are not known to the ASIS Context and cannot be
--        automatically recorded by the
--        Asis.Data_Decomposition.Portable_Transfer generics. For example:
--
--            N : Natural := Function_Call();
--            ....
--            declare
--                type Complex is
--                    record
--                        S1 : Wide_String (1 .. N);
--                    end record;
--            begin
--                ....
--            end;
--
--
--  General Usage Rules:
--
--  All operations in this package will attempt to detect the use of invalid
--  data streams.  A data stream is "invalid" if an operation determines that
--  the stream could not possibly represent a value of the expected variety.
--  Possible errors are: stream is of incorrect length, stream contains bit
--  patterns which are illegal, etc.  The exception ASIS_Inappropriate_Element
--  is raised in these cases.  The Status value is Data_Error.  The
--  Diagnosis string will indicate the kind of error detected.
--
--  All implementations will handle arrays with a minimum of 16 dimensions,
--  or the number of dimensions allowed by their compiler, whichever is
--  smaller.
------------------------------------------------------------------------------
------------------------------------------------------------------------------
--  22.1 type Record_Component
------------------------------------------------------------------------------
--  Record_Component
--
--  Describes one discriminant or component of a record type.  Implementation
--  is highly implementation dependent.  The "=" operator is not meaningful
--  between Record_Component values unless one of them is the
--  Nil_Record_Component value.
--
--  A record type describes composite values which contain zero or more
--  discriminant and component fields.  A_Record_Type_Definition can be
--  queried to obtain a list of Record_Components.  Each Record_Component
--  contains the information necessary to extract one discriminant or
--  component field of the record.
--
--  Record_Components are intended for use with data stream extraction
--  operations.  An extraction operation is performed using a Record_Component,
--  in conjunction with a data stream representing a value of the record type.
--  The record data stream contains data for all fields of the record.  The
--  result is an extracted data stream representing just the value of the one
--  field.  Record_Components are implemented so as to allow for efficient
--  extraction of field values.
--
--  An extracted field data stream is suitable for all uses.  If the field is a
--  scalar type, it can be converted directly into useful information.  If the
--  field is, in turn, another composite value, it can be further decomposed
--  into its own component values.
--
--  There are two ways to obtain the Record_Components or the Array_Component
--  needed to further decompose an embedded composite field.  First, if the
--  type of the field is known, the type definition can be directly queried to
--  obtain the Record_Components or the Array_Component that describe its
--  internal structure.  Second, the Record_Component used to extract the field
--  can be queried to obtain the same Record_Components or the same
--  Array_Component.  Both methods return identical information.
--
--  This kind of nested decomposition can be carried to any required level.
--
--  Record_Components become invalid when the Context, from which they
--  originate, is closed.  All Record_Components are obtained by referencing a)
--  an Element, which has an associated Context, b) another Record_Component,
--  or c) an Array_Component.  Ultimately, all component values originate from
--  a A_Type_Definition Element; that Element determines their Context of
--  origin.
------------------------------------------------------------------------------

   type Record_Component is private;
   Nil_Record_Component : constant Record_Component;

   function "=" (Left  : Record_Component;
                 Right : Record_Component)
                 return  Boolean is abstract;

------------------------------------------------------------------------------
--  22.2 type Record_Component_List
------------------------------------------------------------------------------

   type Record_Component_List is
      array (Asis.List_Index range <>) of Record_Component;

------------------------------------------------------------------------------
--  22.3 type Array_Component
------------------------------------------------------------------------------
--  Array_Component
--
--  Describes the components of an array valued field for a record type.
--  Implementation is highly implementor dependent.  The "=" operator is not
--  meaningful between Array_Component values unless one of them is the
--  Nil_Array_Component value.
--
--  An array type describes composite values which contain zero or more indexed
--  components. Both An_Unconstrained_Array_Definition or
--  A_Constrained_Array_Definition can be queried to obtain a single
--  Array_Component. The Array_Component contains the information necessary to
--  extract any arbitrary component of the array.
--
--  Array_Components are intended for use with data stream extraction
--  operations.  An extraction operation is performed using an Array_Component,
--  in conjunction with a data stream representing a value of the array type.
--  The array data stream contains data for all components of the array.  The
--  result is an extracted data stream representing just the value of the one
--  component.  Array_Components are implemented so as to allow for efficient
--  extraction of array component values.
--
--  An extracted component data stream is suitable for all uses.  If the
--  component is a scalar type, it can be converted directly into useful
--  information.  If the component is, in turn, another composite value, it can
--  be further decomposed into its own component values.
--
--  There are two ways to obtain the Record_Components or the Array_Component
--  needed to further decompose an embedded composite component.  First, if the
--  type of the component is known, the type definition can be directly queried
--  to obtain the Record_Components or the Array_Component that describe its
--  internal structure.  Second, the Array_Component used to extract the
--  component can be queried to obtain the same Record_Components or the same
--  Array_Component.  Both methods return identical information.
--
--  This kind of nested decomposition can be carried to any required level.
--
--  Array_Components become invalid when the Context, from which they
--  originate, is closed.  All Record_Components are obtained by referencing a)
--  an Element, which has an associated Context, b) a Record_Component, or c)
--  another Array_Component.  Ultimately, all component values originate from a
--  A_Type_Definition Element; that Element determines their Context of origin.
------------------------------------------------------------------------------

   type Array_Component is private;
   Nil_Array_Component : constant Array_Component;

   function "=" (Left  : Array_Component;
                 Right : Array_Component)
                 return  Boolean is abstract;

------------------------------------------------------------------------------
--  22.4 type Array_Component_List
------------------------------------------------------------------------------

   type Array_Component_List is
      array (Asis.List_Index range <>) of Array_Component;

------------------------------------------------------------------------------
--  22.5 type Dimension_Indexes
------------------------------------------------------------------------------
--  Dimension_Indexes - an array of index values used to access an array stream
------------------------------------------------------------------------------

   type Dimension_Indexes is
      array (Asis.ASIS_Positive range <>) of Asis.ASIS_Positive;

------------------------------------------------------------------------------
--  22.6 type Array_Component_Iterator
------------------------------------------------------------------------------
--  Array_Component_Iterator - Used to iterate over successive components of an
--  array.  This can be more efficient than using individual index values when
--  extracting array components from a data stream because it substitutes two
--  subroutine calls (Next and Done) for the multiplications and divisions
--  implicit in indexing an N dimensional array with a single index value.
--
--  Iterators can be copied.  The copies operate independently (have separate
--  state).
--
--  An example:
--
--   declare
--       Component        : Array_Component := ...;
--       Iter             : Array_Component_Iterator;
--       Array_Stream     : Portable_Data (...) := ...;
--       Component_Stream : Portable_Data (...);
--   begin
--       Iter := Array_Iterator (Component);
--       while not Done (Iter) loop
--           Component_Stream := Component_Data_Stream (Iter, Array_Stream);
--           Next (Iter);
--       end loop;
--   end;
------------------------------------------------------------------------------

   type Array_Component_Iterator is private;

   Nil_Array_Component_Iterator : constant Array_Component_Iterator;

------------------------------------------------------------------------------
--  22.7 type Portable_Data
------------------------------------------------------------------------------
--
--  Portable Data Representation - an ordered "stream" of data values
--
--  The portable representation for application data is an array of data
--  values.  This portable data representation is guaranteed to be valid when
--  written, and later read, on the same machine architecture, using the same
--  implementor's compiler and runtime system.  Portability of the data
--  values, across implementations and architectures, is not guaranteed.
--  Some implementors may be able to provide data values which are portable
--  across a larger subset of their supported machine architectures.
--
--  Some of the problems encountered when changing architectures are: bit
--  order, byte order, floating point representation, and alignment
--  constraints.  Some of the problems encountered when changing runtime
--  systems or implementations are: type representation, optimization,
--  record padding, and other I/O subsystem implementation variations.
--
--  The nature of these data values is deliberately unspecified.  An
--  implementor will choose a data value type that is suitable for the
--  expected uses of these arrays and data values.  Arrays and data
--  values have these uses:
--
--   a) Array values are used in conjunction with the
--      Asis.Data_Decomposition interface.  The data value type should be
--      readily decomposable, by that package, so that array and record
--      components can be efficiently extracted from a data stream represented
--      by this array type.  The efficiency of that interface is a priority.
--
--   b) The data value type is read and written by applications.  It
--      should have a size that makes efficient I/O possible.  Applications can
--      be expected to perform I/O in any or all of these ways:
--
--       1) Ada.Sequential_Io or Ada.Direct_Io could be used to read or write
--          these values.
--
--       2) Individual values may be placed inside other types and those types
--          may be read or written.
--
--       3) The 'Address of a data value, plus the 'Size of the data value
--          type, may be used to perform low level system I/O.  Note: This
--          requires the 'Size of the type and the 'Size of a variable of that
--          type to be the same for some implementations.
--
--       4) Individual values may be passed through Unchecked_Conversion in
--          order to obtain a different value type, of the same 'Size, suitable
--          for use with some user I/O facility.  This usage is non-portable
--          across implementations.
--
--   c) Array values are read and written by applications.  The data value
--      type should have a size that makes efficient I/O possible.
--      Applications can be expected to perform I/O in any or all of these
--      ways:
--
--       1) Ada.Sequential_Io or Ada.Direct_Io could be used to read or write a
--          constrained array subtype.
--
--       2) Array values may be placed inside other types and those types may
--          be read and written.
--
--       3) The 'Address of the first array value, plus the 'Length of the
--          array times the 'Size of the values, may be used to perform low
--          level system I/O.  Note: This implies that the array type is
--          unpacked, or, that the packed array type has no "padding" (e.g.,
--          groups of five 6-bit values packed into 32-bit words with 2 bits
--          of padding every 5 elements).
--
--       4) Array values may be passed through Unchecked_Conversion in order to
--          obtain an array value, with a different value type, suitable for
--          use with some user I/O facility.  This usage is non-portable across
--          implementations.
--
--  The data value type should be chosen so that the 'Address of the first
--  array data value is also the 'Address of the first storage unit containing
--  array data.  This is especially necessary for target architectures where
--  the "bit" instructions address bits in the opposite direction as that used
--  by normal machine memory (or array component) indexing.  A recommended
--  'Size is System.Storage_Unit (or a multiple of that size).
--
--  Implementations that do not support Unchecked_Conversion of array values,
--  or which do not guarantee that Unchecked_Conversion of array values will
--  always "do the right thing" (convert only the data, and not the dope vector
--  information), should provide warnings in their ASIS documentation that
--  detail possible consequences and work-arounds.
--
--  The index range for the Portable_Data type shall be a numeric type whose
--  range is large enough to encompass the Portable_Data representation for all
--  possible runtime data values.
--
--  All conversion interfaces always return Portable_Data array values with a
--  'First of one (1).
--
--  The Portable_Value type may be implemented in any way
--  whatsoever.  It need not be a numeric type.
------------------------------------------------------------------------------

   type Portable_Value is mod 2 ** 8;

   subtype Portable_Positive is Asis.ASIS_Positive
      range 1 .. Implementation_Defined_Integer_Constant;

   type Portable_Data is array (Portable_Positive range <>) of Portable_Value;

   Nil_Portable_Data : Portable_Data (1 .. 0);

------------------------------------------------------------------------------
--  22.8 type Type_Model_Kinds
------------------------------------------------------------------------------
--  Type_Model_Kinds
--
--  Each Type_Definition fits into one of three type models.
------------------------------------------------------------------------------

   type Type_Model_Kinds is (A_Simple_Static_Model,
                             A_Simple_Dynamic_Model,
                             A_Complex_Dynamic_Model,
                             Not_A_Type_Model);           -- Nil arguments

------------------------------------------------------------------------------
--  22.9 function Type_Model_Kind
------------------------------------------------------------------------------

   function Type_Model_Kind
     (Type_Definition : Asis.Type_Definition)
      return            Type_Model_Kinds;

   function Type_Model_Kind
     (Component : Record_Component)
      return      Type_Model_Kinds;

   function Type_Model_Kind
     (Component : Array_Component)
      return      Type_Model_Kinds;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the type definition to query
--  Component       - Specifies a record field with a record or array type
--
--  Returns the model that best describes the type indicated by the argument.
--  Returns Not_A_Type_Model for any unexpected argument such as a Nil value.
--
--  Expected Element_Kinds:
--      A_Type_Definition
--
--  --|A4G Type_Model_Kind is extended to operate on A_Subtype_Indication
--  --|A4G Elements
------------------------------------------------------------------------------
--  22.10        function Is_Nil
------------------------------------------------------------------------------

   function Is_Nil (Right : Record_Component) return Boolean;

   function Is_Nil (Right : Array_Component)  return Boolean;

------------------------------------------------------------------------------
--  Right   - Specifies the component to check
--
--  Returns True if Right is a Nil (or uninitialized) component value.
--
--  Returns False for all other values.
--
--  All component values are appropriate.
--
------------------------------------------------------------------------------
--  22.11        function Is_Equal
------------------------------------------------------------------------------

   function Is_Equal
     (Left  : Record_Component;
      Right : Record_Component)
      return  Boolean;

   function Is_Equal
     (Left  : Array_Component;
      Right : Array_Component)
      return  Boolean;

------------------------------------------------------------------------------
--  Left    - Specifies the left component to compare
--  Right   - Specifies the right component to compare
--
--  Returns True if Left and Right represent the same physical component of the
--  same record or array type, from the same physical compilation unit.  The
--  two components may or may not be from the same open ASIS Context variable.
--
--  Implies:
--    Is_Equal (Enclosing_Compilation_Unit (Component_Declaration (Left)),
--              Enclosing_Compilation_Unit (Component_Declaration (Right)))
--    = True
--
--  All component values are appropriate.
--
------------------------------------------------------------------------------
--  22.12        function Is_Identical
------------------------------------------------------------------------------

   function Is_Identical
     (Left  : Record_Component;
      Right : Record_Component)
      return  Boolean;

   function Is_Identical
     (Left  : Array_Component;
      Right : Array_Component)
      return  Boolean;

------------------------------------------------------------------------------
--  Left    - Specifies the left component to compare
--  Right   - Specifies the right component to compare
--
--  Returns True if Left and Right represent the same physical component of the
--  same record or array type, from the same physical compilation unit and the
--  same open ASIS Context variable.
--
--  Implies:
--    Is_Identical (Enclosing_Compilation_Unit (Component_Declaration (Left)),
--                  Enclosing_Compilation_Unit (Component_Declaration (Right)))
--    = True
--
--  All component values are appropriate.
--
------------------------------------------------------------------------------
--  22.13        function Is_Array
------------------------------------------------------------------------------

   function Is_Array (Component : Record_Component) return Boolean;

   function Is_Array (Component : Array_Component)  return Boolean;

------------------------------------------------------------------------------
--  Component   - Specifies any component
--
--  Returns True if the component has an array subtype (contains an array
--  value).
--
--  Returns False for Nil components and any component that is not an embedded
--  array.
--
------------------------------------------------------------------------------
--  22.14        function Is_Record
------------------------------------------------------------------------------

   function Is_Record (Component : Record_Component) return Boolean;
   function Is_Record (Component : Array_Component)  return Boolean;

------------------------------------------------------------------------------
--  Component   - Specifies any component
--
--  Returns True if the component has a record subtype.
--  Returns False for Nil components and any component that is not an embedded
--  record.
--

------------------------------------------------------------------------------
--  22.15        function Done
------------------------------------------------------------------------------

   function Done (Iterator : Array_Component_Iterator) return Boolean;

------------------------------------------------------------------------------
--  Iterator    - Specifies the iterator to query
--
--  Returns True if the iterator has been advanced past the last array
--  component.  Returns True for a Nil_Array_Component_Iterator.
--
------------------------------------------------------------------------------
--  22.16        procedure Next
------------------------------------------------------------------------------

   procedure Next (Iterator : in out Array_Component_Iterator);

------------------------------------------------------------------------------
--  Iterator    - Specifies the iterator to advance
--
--  Advances the iterator to the next array component.  Use Done to test the
--  iterator to see if it has passed the last component.  Does nothing if the
--  iterator is already past the last component.
--
------------------------------------------------------------------------------
--  22.17        procedure Reset
------------------------------------------------------------------------------

   procedure Reset (Iterator : in out Array_Component_Iterator);

------------------------------------------------------------------------------
--  Iterator    - Specifies the iterator to reset
--
--  Resets the iterator to the first array component.
--
------------------------------------------------------------------------------
--  22.18        function Array_Index
------------------------------------------------------------------------------

   function Array_Index
     (Iterator : Array_Component_Iterator)
      return     Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Iterator    - Specifies the iterator to query
--
--  Returns the Index value which, when used in conjunction with the
--  Array_Component value used to create the Iterator, indexes the same array
--  component as that presently addressed by the Iterator.
--
--  Raises ASIS_Inappropriate_Element if given a Nil_Array_Component_Iterator
--  or one where Done(Iterator) = True.  The Status value is Data_Error.
--  The Diagnosis string will indicate the kind of error detected.
--
------------------------------------------------------------------------------
--  22.19        function Array_Indexes
------------------------------------------------------------------------------

   function Array_Indexes
     (Iterator : Array_Component_Iterator)
      return     Dimension_Indexes;

------------------------------------------------------------------------------
--  Iterator    - Specifies the iterator to query
--
--  Returns the index values which, when used in conjunction with the
--  Array_Component value used to create the Iterator, indexes the same array
--  component as that presently addressed by the Iterator.
--
--  Raises ASIS_Inappropriate_Element if given a Nil_Array_Component_Iterator
--  or one where Done(Iterator) = True.  The Status value is Data_Error.
--  The Diagnosis string will indicate the kind of error detected.
--
------------------------------------------------------------------------------
--  22.20        function Discriminant_Components
------------------------------------------------------------------------------
   function Discriminant_Components
     (Type_Definition : Asis.Type_Definition)
      return            Record_Component_List;

   function Discriminant_Components
     (Component : Record_Component)
      return      Record_Component_List;

   function Discriminant_Components
     (Component : Array_Component)
      return      Record_Component_List;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the record type definition to query
--  Component       - Specifies a component which has a record subtype,
--                      Is_Record(Component) = True
--
--  Returns a list of the discriminant components for records of the indicated
--  record type.
--
--  The result describes the locations of the record type's discriminants,
--  regardless of the static or dynamic nature of the record type.
--  All return components are intended for use with a data stream representing
--  a value of the indicated record type.
--
--  All Is_Record(Component) = True arguments are appropriate.  All return
--  values are valid parameters for all query operations.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from a record type)
--       A_Record_Type_Definition
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--       A_Simple_Dynamic_Model
--       A_Complex_Dynamic_Model
--
------------------------------------------------------------------------------
--  22.21        function Record_Components
------------------------------------------------------------------------------
   function Record_Components
     (Type_Definition : Asis.Type_Definition)
      return            Record_Component_List;

   function Record_Components
     (Component : Record_Component)
      return      Record_Component_List;

   function Record_Components
     (Component : Array_Component)
      return      Record_Component_List;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the record type definition to query
--  Component       - Specifies a component which has a record subtype,
--                      Is_Record(Component) = True
--
--  Returns a list of the discriminants and components for the indicated simple
--  static record type.  (See rule 6.A above.)
--
--  The result describes the locations of the record type's discriminants and
--  components.  All return components are intended for use with a data stream
--  representing a value of the indicated record type.
--
--  All Is_Record (Component) = True values, having simple static types, are
--  appropriate.  All return values are valid parameters for all query
--  operations.
--
--  Note: If an Ada implementation uses implementation-dependent record
--  components (Reference Manual 13.5.1 (15)), then each such component of
--  the record type is included in the result.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from a record type)
--       A_Record_Type_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--
------------------------------------------------------------------------------
--  22.22        function Record_Components
------------------------------------------------------------------------------

   function Record_Components
     (Type_Definition : Asis.Type_Definition;
      Data_Stream     : Portable_Data)
      return            Record_Component_List;

   function Record_Components
     (Component   : Record_Component;
      Data_Stream : Portable_Data)
      return        Record_Component_List;

   function Record_Components
     (Component   : Array_Component;
      Data_Stream : Portable_Data)
      return        Record_Component_List;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the record type definition to query
--  Component       - Specifies a component which has a record subtype,
--                      Is_Record(Component) = True
--  Data_Stream     - Specifies a data stream containing, at least, the
--                      complete set of discriminant or index constraints for
--                      the type
--
--  Returns a list of the discriminants and components for the indicated record
--  type, using the data stream argument as a guide.  The record type shall be
--  either a simple static, or a simple dynamic, record type.  (See rules 6.A
--  and 6.B above.)
--
--  The result describes the locations of the record type's discriminants and
--  all components of the appropriate variant parts.  The contents of the list
--  are determined by the discriminant values present in the data stream.
--
--  A simple static type will always return the same component list (Is_Equal
--  parts) regardless of the Data_Stream, because the layout of a simple static
--  type does not change with changes in discriminant values.  A simple dynamic
--  type returns different component lists (non-Is_Equal parts) depending on
--  the contents of the Data_Stream, because the contents and layout of a
--  simple dynamic type changes with changes in discriminant values.  All
--  return components are intended for use with a data stream representing a
--  value of the indicate record type.
--
--  The Data_Stream shall represent a fully discriminated value of the
--  indicated record type.  The stream may have been read from a file, it may
--  have been extracted from some enclosing data stream, or it may be an
--  artificial value created by the Construct_Artificial_Data_Stream operation.
--  Only the discriminant portion of the Data_Stream is checked for validity,
--  and, only some discriminant fields may need to be checked, depending on the
--  complexity of the record type.  The best approach, for any application that
--  is constructing artificial data streams, is to always provide appropriate
--  values for all discriminant fields.  It is not necessary to provide values
--  for non-discriminant fields.
--
--  All Is_Record(Component) = True values are appropriate.  All return values
--  are valid parameters for all query operations.
--
--  Note: If an Ada implementation uses implementation-dependent record
--  components (Reference Manual 13.5.1 (15)), then each such component of the
--  record type is included in the result.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from a record type)
--       A_Record_Type_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--       A_Simple_Dynamic_Model
--
------------------------------------------------------------------------------
--  22.23        function Array_Components
------------------------------------------------------------------------------

   function Array_Components
     (Type_Definition : Asis.Type_Definition)
      return            Array_Component;

   function Array_Components
     (Component : Record_Component)
      return      Array_Component;

   function Array_Components
     (Component : Array_Component)
      return      Array_Component;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the array type definition to query
--  Component       - Specifies a component which has an array subtype,
--                      Is_Array(Component) = True
--
--  Returns a single component, describing all components of the indicated
--  array type.  The array type shall be a simple static, or a simple dynamic
--  array type.  (See rules 6.A and 6.B above.)
--
--  The result contains all information necessary to index and extract any
--  component of a data stream representing a value of the indicated array
--  type.
--
--  All Is_Array (Component) = True values are appropriate.  All return values
--  are valid parameters for all query operations.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from an array type)
--       An_Unconstrained_Array_Definition
--       A_Constrained_Array_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--       A_Simple_Dynamic_Model
--
------------------------------------------------------------------------------
--  22.24        function Array_Iterator
------------------------------------------------------------------------------

   function Array_Iterator
     (Component : Array_Component)
      return      Array_Component_Iterator;

------------------------------------------------------------------------------
--  Component   - Specifies an array component to be used for iteration
--
--  Returns an iterator poised to fetch the 1st component of an array.
--

------------------------------------------------------------------------------
--  22.25        function Component_Data_Stream
------------------------------------------------------------------------------

   function Component_Data_Stream
     (Component   : Record_Component;
      Data_Stream : Portable_Data)
      return        Portable_Data;

   function Component_Data_Stream
     (Component   : Array_Component;
      Index       : Asis.ASIS_Positive;
      Data_Stream : Portable_Data)
      return        Portable_Data;

   function Component_Data_Stream
     (Component   : Array_Component;
      Indexes     : Dimension_Indexes;
      Data_Stream : Portable_Data)
      return        Portable_Data;

   function Component_Data_Stream
     (Iterator    : Array_Component_Iterator;
      Data_Stream : Portable_Data)
      return        Portable_Data;

------------------------------------------------------------------------------
--  Component   - Specifies the component or discriminant to be extracted
--  Index       - Specifies an index, 1..Array_Length, within an array
--  Indexes     - Specifies a list of index values, there is one value for
--                  each dimension of the array type, each index N is in the
--                  range 1..Array_Length (Component, N);
--  Iterator    - Specifies the array component to extract
--  Data_Stream - Specifies the data stream from which to extract the result
--
--  Returns a data stream representing just the value of the chosen Component.
--  The return value is sliced from the data stream.  The Data_Stream shall
--  represent a value of the appropriate type.  It may have been obtained from
--  a file, extracted from another data stream, or artificially constructed
--  using the Construct_Artificial_Data_Stream operation.
--
--  An artificial data stream may raise ASIS_Inappropriate_Element (the Status
--  is Value_Error).  Only the constraint values are valid, once they
--  have been properly initialized, and can be safely extracted from an
--  artificial data stream.
--
--  Raises ASIS_Inappropriate_Element if given a Nil_Array_Component_Iterator
--  or one where Done(Iterator) = True.  The Status value is Data_Error.
--  The Diagnosis string will indicate the kind of error detected.
--
--  All non-Nil component values are appropriate.
--
------------------------------------------------------------------------------
--  22.26        function Component_Declaration
------------------------------------------------------------------------------

   function Component_Declaration
     (Component : Record_Component)
      return      Asis.Declaration;

------------------------------------------------------------------------------
--  Component   - Specifies the component to be queried
--
--  Returns an Asis.Declaration, which is either A_Component_Declaration
--  or A_Discriminant_Specification.  These values can be used to determine the
--  subtype, type, and base type of the record component.  The result may be an
--  explicit declaration made by the user, or, it may be an implicit
--  component declaration for an implementation-defined component (Reference
--  Manual 13.5.1(15)).
--
--  All non-Nil component values are appropriate.
--
--  Returns Element_Kinds:
--       A_Declaration
--
--  Returns Declaration_Kinds:
--       A_Component_Declaration
--       A_Discriminant_Specification
--
------------------------------------------------------------------------------
--  22.27        function Component_Indication
------------------------------------------------------------------------------

   function Component_Indication
     (Component : Array_Component)
      return      Asis.Subtype_Indication;

------------------------------------------------------------------------------
--  Component   - Specifies the component to be queried
--
--  Returns an Asis.Subtype_Indication.  These values can be used to determine
--  the subtype, type, and base type of the array components.
--
--  All non-Nil component values are appropriate.
--
--  Returns Element_Kinds:
--       A_Subtype_Indication
--
------------------------------------------------------------------------------
--  22.28        function All_Named_Components
------------------------------------------------------------------------------

   function All_Named_Components
     (Type_Definition : Asis.Type_Definition)
      return            Asis.Defining_Name_List;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the record type definition to query
--
--  Returns a list of all discriminant and component entity names defined by
--  the record type.  All record type definitions are appropriate for this
--  operation.  This query provides a means for determining whether a field,
--  with a particular name, exists for some possible instance of the record
--  type.  This list does not include the names of implementation-defined
--  components (Reference Manual 13.5.1 (15)); those name have the form of
--  An_Attribute_Reference expression.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from a record type)
--       A_Record_Type_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--       A_Simple_Dynamic_Model
--       A_Complex_Dynamic_Model
--
------------------------------------------------------------------------------
--  22.29        function Array_Length
------------------------------------------------------------------------------

   function Array_Length
     (Component : Record_Component)
      return      Asis.ASIS_Natural;

   function Array_Length
     (Component : Array_Component)
      return      Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Component   - Specifies the component to query
--
--  Returns the number of components within an array valued component.  The
--  array subtype may be multidimensional.  The result treats the array as if
--  it were unidimensional.  It is the product of the 'Lengths of the
--  individual array dimensions.
--
--  All Is_Array(Component) = True values are appropriate.
--
------------------------------------------------------------------------------
--  22.30        function Array_Length
------------------------------------------------------------------------------

   function Array_Length
     (Component : Record_Component;
      Dimension : Asis.ASIS_Natural)
      return      Asis.ASIS_Natural;

   function Array_Length
     (Component : Array_Component;
      Dimension : Asis.ASIS_Natural)
      return      Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Component   - Specifies the component to query
--  Dimension   - Specifies the array dimension to query
--
--  Returns the number of components within an array valued component.  The
--  array subtype may be unidimensional.  The result is the 'Length(Dimension)
--  of the array.
--
--  All Is_Array(Component) = True values are appropriate.
--
------------------------------------------------------------------------------
--  22.31        function Size
------------------------------------------------------------------------------

   function Size
     (Type_Definition : Asis.Type_Definition)
      return            Asis.ASIS_Natural;

   function Size
     (Component : Record_Component)
      return Asis.ASIS_Natural;

   function Size
     (Component : Array_Component)
      return Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Type_Definition - Specifies a type definition, whose 'Size is desired
--  Component       - Specifies a component, whose 'Size is desired
--
--  Returns the minimum number of bits required to hold a simple static type,
--  the number of bits allocated to hold a record field, or the number of bits
--  allocated to hold each array component.
--
--  --|AN Application Note:
--  --|AN
--  --|AN For components, this is the number of bits allocated
--  --|AN within the composite value.  It may be greater than the number
--  --|AN of bits occupied by data values of this component type.
--  --|AN Also, the data value, when occupying more space than is
--  --|AN minimally required, may be preceded, followed, or surrounded by
--  --|AN padding bits which are necessary to fully occupy the space allotted.
--  --|AN
--  All non-Nil component values are appropriate.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--
--  --|A4G Size is extended to operate on A_Subtype_Indication
--  --|A4G Elements
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--
------------------------------------------------------------------------------
--  22.32        function Size
------------------------------------------------------------------------------

   function Size
     (Type_Definition : Asis.Type_Definition;
      Data_Stream     : Portable_Data)
      return            Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the type definition to query
--  Data_Stream     - Specifies a data stream containing, at least, the
--                    complete set of discriminant or index constraints for
--                    the type
--
--  Returns the 'Size of a value of this type, with these constraints.  This is
--  the minimum number of bits that is needed to hold any possible value of the
--  given fully constrained subtype.  Only the constraint portion of the
--  Data_Stream is checked.
--
--  The Data_Stream may be a data stream or it may be an artificial
--  data stream created by the Construct_Artificial_Data_Stream operation.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--       A_Simple_Static_Model
--       A_Simple_Dynamic_Model
--
------------------------------------------------------------------------------
--  22.33        function Position
------------------------------------------------------------------------------

   function Position
     (Component : Record_Component)
      return      Asis.ASIS_Natural;

   function Position
     (Component : Array_Component;
      Index     : Asis.ASIS_Positive)
      return      Asis.ASIS_Natural;

   function Position
     (Component : Array_Component;
      Indexes   : Dimension_Indexes)
      return      Asis.ASIS_Natural;

   function Position
     (Iterator : Array_Component_Iterator)
      return     Asis.ASIS_Natural;

------------------------------------------------------------------------------
--  Component   - Specifies the component to query
--  Index       - Specifies a value in the range 1..Array_Length (Component),
--                the index of the component to query
--  Indexes     - Specifies a list of index values, there is one value for
--                each dimension of the array type, each index N is in the
--                range 1..Array_Length (Component, N);
--  Iterator    - Specifies a particular array component to query
--
--  Returns the System.Storage_Unit offset, from the start of the first storage
--  unit occupied by the enclosing composite type, of the first of the storage
--  units occupied by the Component.  The offset is measured in storage units.
--
--  All non-Nil component values are appropriate.  Raises
--  ASIS_Inappropriate_Element with a Status of Data_Error if any index is not
--  in the expected range or if Done (Iterator) = True.  The Status value will
--  be Data_Error.  The Diagnosis string will indicate the kind of error
--  detected.
--
------------------------------------------------------------------------------
--  22.34        function First_Bit
------------------------------------------------------------------------------

   function First_Bit
     (Component : Record_Component)
      return      Asis.ASIS_Natural;

   function First_Bit
     (Component : Array_Component;
      Index     : Asis.ASIS_Positive)
      return      Asis.ASIS_Natural;

   function First_Bit
     (Component : Array_Component;
      Indexes   : Dimension_Indexes)
      return      Asis.ASIS_Natural;

   function First_Bit
     (Iterator : Array_Component_Iterator)
      return     Asis.ASIS_Natural;

------------------------------------------------------------------------------

--  Component   - Specifies the component to query
--  Index       - Specifies a value in the range 1..Array_Length (Component),
--                the index of the component to query
--  Indexes     - Specifies a list of index values, there is one value for
--                each dimension of the array type, each index N is in the
--                range 1..Array_Length (Component, N);
--  Iterator    - Specifies a particular array component to query
--
--  Returns the bit offset, from the start of the first of the storage units
--  occupied by the Component, of the first bit occupied by the Component.  The
--  offset is measured in bits.
--
--  All non-Nil component values are appropriate.  Raises
--  ASIS_Inappropriate_Element with a Status of Data_Error if any index is not
--  in the expected range or if Done (Iterator) = True.  The Status value will
--  be Data_Error.  The Diagnosis string will indicate the kind of error
--  detected.
--
------------------------------------------------------------------------------
--  22.35        function Last_Bit
------------------------------------------------------------------------------

   function Last_Bit
     (Component : Record_Component)
      return      Asis.ASIS_Integer;

   function Last_Bit
     (Component : Array_Component;
      Index     : Asis.ASIS_Positive)
      return      Asis.ASIS_Integer;

   function Last_Bit
     (Component : Array_Component;
      Indexes   : Dimension_Indexes)
      return      Asis.ASIS_Integer;

   function Last_Bit
     (Iterator : Array_Component_Iterator)
      return     Asis.ASIS_Integer;

------------------------------------------------------------------------------
--  Component   - Specifies the component to query
--  Index       - Specifies a value in the range 1..Array_Length (Component),
--                the index of the component to query
--  Indexes     - Specifies a list of index values, there is one value for
--                each dimension of the array type, each index N is in the
--                range 1..Array_Length (Component, N);
--  Iterator    - Specifies a particular array component to query
--
--  Returns the bit offset, from the start of the first of the storage units
--  occupied by the Index'th Element, of the last bit occupied by the Element.
--  The offset is measured in bits.
--
--  Note, that Last_Bit may be equal to -1 for a component which is
--  an empty array
--
--  All non-Nil component values are appropriate.  Raises
--  ASIS_Inappropriate_Element with a Status of Data_Error if any index is not
--  in the expected range or if Done (Iterator) = True.  The Status value will
--  be Data_Error.  The Diagnosis string will indicate the kind of error
--  detected.
--
------------------------------------------------------------------------------
--  22.36        function Portable_Constrained_Subtype
------------------------------------------------------------------------------
--  Generic for Data Stream Conversions
------------------------------------------------------------------------------

   generic
      --  Ada notation for a constrained subtype.
      --  type Constrained_Subtype (<>) is private;
      type Constrained_Subtype is private;
   function Portable_Constrained_Subtype
     (Data_Stream : Portable_Data)
      return        Constrained_Subtype;

------------------------------------------------------------------------------
--  Data_Stream - Specifies an extracted component of a record
--
--  Instantiated with an appropriate scalar type, (e.g., System.Integer, can be
--  used to convert a data stream to a value that can be directly examined).
--
--  Instantiated with a record type, can be used to convert a data stream to a
--  value that can be directly examined.
--
--  Instantiations with constrained array subtypes may not convert array values
--  if they were created using the Portable_Array_Type_1,
--  Portable_Array_Type_2, or Portable_Array_Type_3 interfaces.
--
--  May raise Constraint_Error if the subtype is a scalar and the converted
--  value is not in the subtype's range.
--
------------------------------------------------------------------------------
--  22.37        function Construct_Artificial_Data_Stream
------------------------------------------------------------------------------

   function Construct_Artificial_Data_Stream
     (Type_Definition : Asis.Type_Definition;
      Data_Stream     : Portable_Data;
      Discriminant    : Record_Component;
      Value           : Portable_Data)
      return            Portable_Data;

------------------------------------------------------------------------------
--  Type_Definition - Specifies the record type definition for the record
--                    valued data stream being constructed
--  Data_Stream     - Specifies the data stream constructed so far; initially
--                    specified as the Nil_Portable_Data value
--  Discriminant    - Specifies the discriminant of the record type that is
--                    being set or changed
--  Value           - Specifies a data stream representing a single
--                    discriminant value of the appropriate type
--
--  Used to artificially construct a data stream which represents the
--  discriminant portion of a fully constrained value of the indicated record
--  type.  This operation is called once with a value for each discriminant of
--  the record type (the order in which the discriminants are specified is not
--  important).  The return value of each call is used as the input Data_Stream
--  for the next.
--
--  The resulting artificial data stream may be used solely for the purpose of
--  creating Record_Component values.  The values of any non-discriminant
--  fields are arbitrary and quite possibly invalid.  The resulting
--  component values may then be used for any purpose.  In particular, they may
--  be used to determine First_Bit, Last_Bit, and Size values for all record
--  discriminants and components.
--
--  Appropriate Element_Kinds:
--       A_Type_Definition
--
--  Appropriate Type_Kinds:
--       A_Derived_Type_Definition       (derived from a record type)
--       A_Record_Type_Definition
--
--
--  ??? Should be extended for A_Subtype_Indication
--
--  Raises ASIS_Inappropriate_Element, with a Status of Data_Error, if the
--  discriminant Value is inappropriate for the specified Discriminant.
--
------------------------------------------------------------------------------

private

   pragma Ordered (Type_Model_Kinds);

   type Portable_Data_Access is access all Portable_Data;
   --  ??? Do we have to keep the whole parent stream? Is not a list
   --  ??? of parent discriminants (in the form suitable for A4G.DDA_Aux)
   --  ??? enough?

   type Discrim_List_Access is access all Discrim_List;

   type Record_Component is record

      Parent_Record_Type : Asis.Definition := Nil_Element;
      --  The definition of the type from which this component was extracted
      --  ??? Do we really need this?

      Component_Name : Asis.Defining_Name := Nil_Element;
      --  The defining name corresponding to the component in
      --  Parent_Record_Type
      --  ??? Why not just keep the entity node?

      Is_Record_Comp : Boolean := False;
      --  Flag indcating if the component itself is of a record type

      Is_Array_Comp : Boolean := False;
      --  Flag indcating if the component itself is of an array type

      Position : ASIS_Natural := 0;
      --  Position of the component, as it is to be returned by
      --  Position query

      First_Bit : ASIS_Natural := 0;
      --  Component first bit, as it is to be returned by First_Bit query

      Last_Bit : ASIS_Integer := 0;
      --  Component last bit, as it is to be returned by Last_Bit query
      --  Note, that Last_Bit may be equal to -1 for a component which is
      --  an empty array

      Size : ASIS_Natural := 0;
      --  Component size, as it is to be returned by Size query

      Parent_Discrims : Discrim_List_Access := null;
      --  The reference to a list of discriminants from the enclosed record
      --  value (null if there is no discriminant)

      Parent_Context : Context_Id := Non_Associated;
      --  An ASIS Context from which a given component is originated

      Obtained : ASIS_OS_Time := Nil_ASIS_OS_Time;
      --  Time when a given component was created, needed for validity
      --  checks

      --  What else do we need???

      --  ??? Do we need the reference to a tree file from which the
      --  ??? component is obtained (plus tree swapping mechanism similar
      --  ??? to what is used for Elements

   end record;

   Nil_Record_Component : constant Record_Component :=
     (Parent_Record_Type => Nil_Element,
      Component_Name     => Nil_Element,
      Is_Record_Comp     => False,
      Is_Array_Comp      => False,
      Position           => 0,
      First_Bit          => 0,
      Last_Bit           => 0,
      Size               => 0,
      Parent_Discrims    => null,
      Parent_Context     => Non_Associated,
      Obtained           => Nil_ASIS_OS_Time);

   type Dimention_Length is array (1 .. 16) of Asis.ASIS_Natural;

   type Array_Component is  record

      --  ??? Currently, the same structure as for Record_Component

      Parent_Array_Type : Asis.Definition := Nil_Element;
      --  The definition of the Array type to which this component
      --  belongs ???

      Array_Type_Entity : Entity_Id := Empty;
      --  Entyty Id for the array type from which the array component was
      --  extracted. It may not correspond to Parent_Array_Type, and it may
      --  be the implicit type entity as well.

      Parent_Component_Name : Asis.Defining_Name := Nil_Element;
      --  The defining name corresponding to the record component (which is of
      --  array type) to which a given array componnets directly belonds
      --  (Nil_Element, if the array component is not directly extracted from
      --  some record component). It may contain index constraint, so we
      --  need it. We also need it to compare array components.

      Is_Record_Comp : Boolean := False;
      --  Flag indcating if the component itself is of a record type

      Is_Array_Comp : Boolean := False;
      --  Flag indcating if the component itself is of an array type

      Position : ASIS_Natural := 0;
      --  Position of the component, as it is to be returned by
      --  Position query

      First_Bit : ASIS_Natural := 0;
      --  Component first bit, as it is to be returned by First_Bit query

      Last_Bit : ASIS_Integer := 0;
      --  Component last bit, as it is to be returned by Last_Bit query
      --  Note, that Last_Bit may be equal to -1 for a component which is
      --  an empty array

      Size : ASIS_Natural := 0;
      --  Component size, as it is to be returned by Size query

      Parent_Discrims : Discrim_List_Access := null;
      --  The reference to a list of discriminants from the enclosed record
      --  value (null if there is no discriminant), needed in case when the
      --  array componnet is extracted from a record component which in turn
      --  depends on discriminant

      Parent_Context : Context_Id := Non_Associated;
      --  An ASIS Context from which a given component is originated

      Obtained : ASIS_OS_Time := Nil_ASIS_OS_Time;
      --  Time when a given component was created, needed for validity
      --  checks

      --  What else do we need???

      Dimension : ASIS_Natural range 1 .. 16;
      --  Dimension of enclosing array value

      Length : Dimention_Length := (others => 0);

   end record;

   Nil_Array_Component : constant Array_Component :=
     (Parent_Array_Type     => Nil_Element,
      Array_Type_Entity     => Empty,
      Parent_Component_Name => Nil_Element,
      Is_Record_Comp        => False,
      Is_Array_Comp         => False,
      Position              => 0,
      First_Bit             => 0,
      Last_Bit              => 0,
      Size                  => 0,
      Parent_Discrims       => null,
      Parent_Context        => Non_Associated,
      Obtained              => Nil_ASIS_OS_Time,
      Dimension             => 1,
      Length                => (others => 0));

   type Array_Component_Iterator is
       record
           Component : Array_Component;
           Max_Len   : Asis.ASIS_Natural := 0;
           Index     : Asis.ASIS_Natural := 0;
       end record;

   Nil_Array_Component_Iterator : constant Array_Component_Iterator :=
      (Component => Nil_Array_Component,
       Max_Len   => 0,
       Index     => 0);

------------------------------------------------------------------------------

end Asis.Data_Decomposition;
