-------------------------------------------------------------------------------
-- (C) Altran Praxis Limited
-------------------------------------------------------------------------------
--
-- The SPARK toolset 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. The SPARK toolset 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. See the GNU General
-- Public License for more details. You should have received a copy of the GNU
-- General Public License distributed with the SPARK toolset; see file
-- COPYING3. If not, go to http://www.gnu.org/licenses for a complete copy of
-- the license.
--
--=============================================================================

--------------------------------------------------------------------------------
--  CompleteCheck
--
--  Purpose:
--   This file implements the completeness checker component described in
--  S.P0468.41.1 and S.P0468.50.3, as part of work package S.P0468.47.1
--
--   The completeness checker supplies an ADT which keeps track of the elements
--  of a type which have been defined in an array aggregate or case
--  statement.
--
--  Clients:
--   Most notable Sem.Compunit and all its subunits that handle
--  Aggregates and Case Statements.
--
--  Use:
--   1. Initialization
--   2. Indicate that a single element has been seen
--   3. Indicate that a range of elements has been seen
--   Repeat 2 - 3 as necessary, then
--   4. Indicate that an others clause has been seen
--   5. Check whether the whole type has been covered
--
--  Extension:
--   This package is currently limited to checking sets whose
--  cardinality does not exceed ExaminerConstants.CompleteCheckSize.
--
--   A future implementation should remove this restriction.
--------------------------------------------------------------------------------

with ExaminerConstants;

--# inherit ExaminerConstants,
--#         Maths;

package CompleteCheck is

   -- the following are the types used to return status values to
   -- the calling environment

   type TypElementState is (Seen, NotSeen);
   type TypOverlapState is (Overlap, NoOverlap);
   type TypRangeState is (RangeTooBig, RangeDoesFit);
   type TypCompleteState is (Complete, Incomplete);

   subtype ElementArrayIndex is Integer range 0 .. ExaminerConstants.CompleteCheckSize - 1;

   type ElementArray is array (ElementArrayIndex) of Boolean;
   pragma Pack (ElementArray);

   type T is record
      LowerBound       : Integer;
      ActualUpperBound : Integer;
      OthersClause     : TypElementState;
      Elements         : ElementArray;
      Undeterminable   : Boolean;
   end record;

   NullT : constant T :=
     T'
     (LowerBound       => 0,
      ActualUpperBound => 0,
      OthersClause     => NotSeen,
      Elements         => ElementArray'(others => False),
      Undeterminable   => False);

   ------------------------------------------------------------------------------
   -- initialize a data type to check completeness
   -- corresponds to the Init schema in the Z spec
   procedure Init
     (Data       :    out T;
      RangeFrom  : in     Integer;
      RangeTo    : in     Integer;
      RangeState :    out TypRangeState);
   --# derives Data,
   --#         RangeState from RangeFrom,
   --#                         RangeTo;
   --# pre RangeFrom <= RangeTo;
   --# post   ((RangeState = RangeDoesFit) <->
   --#           (RangeTo - RangeFrom + 1) <= ExaminerConstants.CompleteCheckSize)
   --#   and ((RangeState = RangeTooBig) <->
   --#          (RangeTo - RangeFrom + 1) > ExaminerConstants.CompleteCheckSize)
   --#   and (Data.ActualUpperBound - Data.LowerBound <
   --#          ExaminerConstants.CompleteCheckSize);

   ------------------------------------------------------------------------------
   -- indicate that a single element has been seen
   -- corresponds to the SeenElement schema.
   -- The OutOfRangeSeen flag indicates whether part or all of the range
   -- imported is outside the range over which the completeness checker is
   -- operating
   procedure SeenElement
     (Data           : in out T;
      ElementNum     : in     Integer;
      OutOfRangeSeen :    out Boolean;
      OverlapState   :    out TypOverlapState);
   --# derives Data,
   --#         OutOfRangeSeen,
   --#         OverlapState   from Data,
   --#                             ElementNum;
   --# pre (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);
   --# post (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);

   ------------------------------------------------------------------------------
   -- indicate that a range has been seen
   -- corresponds to the SeenRange schema.
   -- The OutOfRangeSeen flag indicates whether part or all of the range
   -- imported is outside the range over which the completeness checker is
   -- operating
   procedure SeenRange
     (Data           : in out T;
      RangeFrom      : in     Integer;
      RangeTo        : in     Integer;
      OutOfRangeSeen :    out Boolean;
      OverlapState   :    out TypOverlapState);
   --# derives Data,
   --#         OutOfRangeSeen,
   --#         OverlapState   from Data,
   --#                             RangeFrom,
   --#                             RangeTo;
   --# pre (RangeFrom <= RangeTo) and
   --#   (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);
   --# post (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);

   ------------------------------------------------------------------------------
   -- indicate that an others clause has been seen
   -- corresponds to the SeenOthers schema
   procedure SeenOthers (Data : in out T);
   --# derives Data from *;
   --# pre (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);
   --# post (Data.ActualUpperBound - Data.LowerBound < ExaminerConstants.CompleteCheckSize);

   ------------------------------------------------------------------------------
   -- report whether the type has been completely covered
   -- corresponds to the IsComplete schema
   function IsComplete (Data : T) return TypCompleteState;
   --# pre (Data.ActualUpperBound - Data.LowerBound <
   --#        ExaminerConstants.CompleteCheckSize) or (Data.OthersClause = Seen);
   ------------------------------------------------------------------------------

end CompleteCheck;
