-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

with Cell_Storage;
with Cells;

--# inherit Cells,
--#         Cell_Storage,
--#         Clists,
--#         CStacks,
--#         SPARK_IO,
--#         SP_Symbols,
--#         Statistics,
--#         Structures;
package Pairs is

   ---------------------------------------------------------------------------
   -- This package provides an ADT for a "Pair" structure built within
   -- the Cells.Heap_Record data structure.
   --
   -- A "Pair" is a 2-valued tuple, which can either be:
   --
   -- A "predicate" and an "action"
   -- OR
   -- A Verification Condition, consisting of a Hypotheses and Conclusions
   -- (both of which are actually just an FDL predicate)
   --
   -- Whether a particular Pair represents a predicate/action or a VC
   -- depends on the context of the calling unit.
   ---------------------------------------------------------------------------
   type Pair is private;

   type CombinationKind is (PredicateTransformation, ActionComposition);

   ----------------------------------------------------------------------------
   -- A NullPair is synonymous with Cells.Null_Cell
   ----------------------------------------------------------------------------
   function IsNullPair (P : Pair) return Boolean;

   ----------------------------------------------------------------------------
   -- Returns True if the predicate or hypotheses part is Null
   ----------------------------------------------------------------------------
   function IsTrue (Heap : Cells.Heap_Record;
                    P    : Pair) return Boolean;

   ----------------------------------------------------------------------------
   -- Returns True if the Action part is Null
   ----------------------------------------------------------------------------
   function IsUnitAction (Heap : Cells.Heap_Record;
                          P    : Pair) return Boolean;

   ----------------------------------------------------------------------------
   -- Conversion function to/from Cells.Cell
   ----------------------------------------------------------------------------
   function CellToPair (C : Cells.Cell) return Pair;
   function PairHead (P : Pair) return Cells.Cell;

   ----------------------------------------------------------------------------
   -- Deep copy Original to Copy, following B_Ptr and C_Ptr
   -- fields, but ignoring A_Ptr field.
   ----------------------------------------------------------------------------
   procedure CopyPair (Heap     : in out Cells.Heap_Record;
                       Original : in     Pair;
                       Copy     :    out Pair);
   --# global in out Statistics.TableUsage;
   --# derives Copy,
   --#         Heap                  from Heap,
   --#                                    Original &
   --#         Statistics.TableUsage from *,
   --#                                    Heap,
   --#                                    Original;

   -- Action_R is the structure of an action R
   -- Predicate_q is the structure of a predicate q
   procedure CombinePredicateWithAction
     (Heap                  : in out Cells.Heap_Record;
      Action_R, Predicate_q : in     Cells.Cell;
      Result                :    out Cells.Cell);
   --# global in out Statistics.TableUsage;
   --# derives Heap,
   --#         Statistics.TableUsage from *,
   --#                                    Action_R,
   --#                                    Heap,
   --#                                    Predicate_q &
   --#         Result                from Predicate_q;

   -- Action_R is the structure of an action R
   -- Action_S is the structure of an action S
   procedure ComposeActions (Heap               : in out Cells.Heap_Record;
                             Action_R, Action_S : in     Cells.Cell;
                             Result             :    out Cells.Cell);
   --# global in out Statistics.TableUsage;
   --# derives Heap,
   --#         Statistics.TableUsage from *,
   --#                                    Action_R,
   --#                                    Action_S,
   --#                                    Heap &
   --#         Result                from Action_R;

   ----------------------------------------------------------------------------
   -- FormConjunction
   --
   -- Returns Result = Predicate_1 and Predicate_2
   --
   -- Note the Result refers to the original Predicates in-place - a deep
   -- copy of them is NOT taken.
   --
   -- NOTE: this subprogram doesn't really involve Pairs at all,
   -- so it might be better if located in Cells package instead.
   ----------------------------------------------------------------------------
   procedure FormConjunction
     (Heap                     : in out Cells.Heap_Record;
      Predicate_1, Predicate_2 : in     Cells.Cell;
      Result                   :    out Cells.Cell);
   --# global in out Statistics.TableUsage;
   --# derives Heap                  from *,
   --#                                    Predicate_1,
   --#                                    Predicate_2 &
   --#         Result                from Heap &
   --#         Statistics.TableUsage from *,
   --#                                    Heap;

   ----------------------------------------------------------------------------
   -- MultiplyPairs
   --
   -- Given two predicate-action pairs (p, R) and (q, S) this procedure forms
   -- their product (p and q!R, R.S).
   --
   -- q!R denotes predicate q with assignments in action R substituted
   -- a la Hoare's assignment axiom.
   --
   -- R.S denotes the "action composition" of actions R and S
   ----------------------------------------------------------------------------
   procedure MultiplyPairs (Heap                     : in out Cells.Heap_Record;
                            Multiplicand, Multiplier : in     Pair;
                            Product                  :    out Pair);
   --# global in out Statistics.TableUsage;
   --# derives Heap,
   --#         Statistics.TableUsage from *,
   --#                                    Heap,
   --#                                    Multiplicand,
   --#                                    Multiplier &
   --#         Product               from Heap;

private

   ----------------------------------------------------------------------------
   -- A Pair is actually just a Cells.Cell value, but made
   -- distinct here to prevent unintentional mixing of
   -- Cells and Pairs.
   --
   -- Representation:
   --
   --  The A_Ptr field is used to link together lists of Pairs.
   --
   --  The B_Ptr field of a Pair references the "predicate" or "hypotheses" part
   --
   --  The C_Ptr field of a Pair references the "action" or "conclusions" part
   ----------------------------------------------------------------------------

   type Pair is range 0 .. Cell_Storage.Cell'Last;
   --# assert Pair'Base is Integer;
end Pairs;
