
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
-- 22	package Asis.Data_Decomposition (optional)
---------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------
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
---------------------------------------------------------------------------------------
-- Type 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  : in Record_Component;
                  Right : in 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
---------------------------------------------------------------------------------------
-- Type 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  : in Array_Component;
                  Right : in 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
---------------------------------------------------------------------------------------
-- Type Array_Component_Iterator is 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 represents 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 (Implementation_Defined);

    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 : in Asis.Type_Definition)
                             return Type_Model_Kinds;

    function Type_Model_Kind (Component : in Record_Component)
                             return Type_Model_Kinds;

    function Type_Model_Kind (Component : in 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
--
---------------------------------------------------------------------------------------
-- 22.10	function Is_Nil
---------------------------------------------------------------------------------------

    function Is_Nil (Right : in Record_Component) return Boolean;

    function Is_Nil (Right : in 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  : in Record_Component;  
                       Right : in Record_Component) return Boolean;

    function Is_Equal (Left  : in Array_Component;  
                       Right : in 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  : in Record_Component;  
                           Right : in Record_Component) return Boolean;

    function Is_Identical (Left  : in Array_Component;  
                           Right : in 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 : in Record_Component) return Boolean;

    function Is_Array (Component : in 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 : in Record_Component) return Boolean;
    function Is_Record (Component : in 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 : in 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 : in 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 : in 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 : in Asis.Type_Definition)
                                     return Record_Component_List;

    function Discriminant_Components (Component : in Record_Component)  
                                     return Record_Component_List;

    function Discriminant_Components (Component : in 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
--
-- 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 : in Asis.Type_Definition)
                               return Record_Component_List;

    function Record_Components (Component : in Record_Component)
                               return Record_Component_List;

    function Record_Components (Component : in 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
--
-- Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--      A_Simple_Static_Model
--
---------------------------------------------------------------------------------------
-- 22.22	function Record_Components
---------------------------------------------------------------------------------------

    function Record_Components 
                (Type_Definition : in Asis.Type_Definition;
                 Data_Stream     : in Portable_Data)
                return Record_Component_List;

    function Record_Components 
                (Component   : in Record_Component;
                 Data_Stream : in Portable_Data)
                return Record_Component_List;

    function Record_Components 
                (Component   : in Array_Component;
                 Data_Stream : in 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
--
-- 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 : in Asis.Type_Definition)
                              return Array_Component;

    function Array_Components (Component : in Record_Component)  
                              return Array_Component;

    function Array_Components (Component : in 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
--
-- Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--      A_Simple_Static_Model
--      A_Simple_Dynamic_Model
--
---------------------------------------------------------------------------------------
-- 22.24	function Array_Iterator
---------------------------------------------------------------------------------------

    function Array_Iterator (Component : in 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   : in Record_Component;  
                 Data_Stream : in Portable_Data)  
                return Portable_Data;

    function Component_Data_Stream 
                (Component   : in Array_Component;  
                 Index       : in Asis.ASIS_Positive;  
                 Data_Stream : in Portable_Data)  
                return Portable_Data;

    function Component_Data_Stream 
                (Component   : in Array_Component;  
                 Indexes     : in Dimension_Indexes;  
                 Data_Stream : in Portable_Data)  
                return Portable_Data;

    function Component_Data_Stream 
                (Iterator    : in Array_Component_Iterator;
                 Data_Stream : in 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 : in 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 : in 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 : in 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
--
-- 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 : in Record_Component)  
                          return Asis.ASIS_Natural;

    function Array_Length (Component : in 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 : in Record_Component;
                           Dimension : in Asis.ASIS_Natural)  
                          return Asis.ASIS_Natural;

    function Array_Length (Component : in Array_Component;
                           Dimension : in 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 : in Asis.Type_Definition)
                  return Asis.ASIS_Natural;

    function Size (Component : in Record_Component) return Asis.ASIS_Natural;

    function Size (Component : in 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.
--
-- All non-Nil component values are appropriate.
--
-- Appropriate Element_Kinds:
--      A_Type_Definition
--
-- Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--      A_Simple_Static_Model
--
---------------------------------------------------------------------------------------
-- 22.32	function Size
---------------------------------------------------------------------------------------

    function Size (Type_Definition : in Asis.Type_Definition;
                   Data_Stream     : in 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
--
-- Appropriate Asis.Data_Decomposition.Type_Model_Kinds:
--      A_Simple_Static_Model
--      A_Simple_Dynamic_Model
--
---------------------------------------------------------------------------------------
-- 22.33	function Position
---------------------------------------------------------------------------------------

    function Position (Component : in Record_Component)
                      return Asis.ASIS_Natural;

    function Position (Component : in Array_Component;
                       Index     : in Asis.ASIS_Positive)  
                      return Asis.ASIS_Natural;

    function Position (Component : in Array_Component;
                       Indexes   : in Dimension_Indexes)  
                      return Asis.ASIS_Natural;

    function Position (Iterator : in 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 : in Record_Component)
                       return Asis.ASIS_Natural;

    function First_Bit (Component : in Array_Component;
                        Index     : in Asis.ASIS_Positive)
                       return Asis.ASIS_Natural;

    function First_Bit (Component : in Array_Component;
                        Indexes   : in Dimension_Indexes)
                       return Asis.ASIS_Natural;

    function First_Bit (Iterator : in 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 : in Record_Component)
                      return Asis.ASIS_Natural;

    function Last_Bit (Component : in Array_Component;
                       Index     : in Asis.ASIS_Positive)  
                      return Asis.ASIS_Natural;

    function Last_Bit (Component : in Array_Component;
                       Indexes   : in Dimension_Indexes)
                      return Asis.ASIS_Natural;

    function Last_Bit (Iterator : in 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 Index'th Element, of the last bit occupied by the Element.
-- 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.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 : in 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 : in Asis.Type_Definition;
                 Data_Stream     : in Portable_Data;
                 Discriminant    : in Record_Component;
                 Value           : in 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
--
-- Raises ASIS_Inappropriate_Element, with a Status of Data_Error, if the
-- discriminant Value is inappropriate for the specified Discriminant.
--
---------------------------------------------------------------------------------------


private

    type Record_Component is 
        record
            A : Boolean;
        end record;

    Nil_Record_Component : constant Record_Component := (A => False);

    type Array_Component is 
        record
            A : Boolean;
        end record;

    Nil_Array_Component : constant Array_Component := (A => False);

    type Array_Component_Iterator is 
        record
            Component : Array_Component;
            Index     : Asis.ASIS_Natural := 0;
        end record;

    Nil_Array_Component_Iterator : constant Array_Component_Iterator :=
       (Component => Nil_Array_Component,  
        Index     => 0);

---------------------------------------------------------------------------------------

end Asis.Data_Decomposition;
