-------------------------------------------------------------------------------
-- (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 Cells;
with Dictionary;

use type Dictionary.Symbol;

--# inherit Cells,
--#         Dictionary,
--#         SPARK_IO,
--#         Statistics;
package Pile is
   ---------------------------------------------------------------------
   -- A "Pile" is an ordered set of Cells built within a Heap structure
   --
   -- Each entry contains a Value of type Dictionary.Symbol
   --
   -- The pile is a set, so there are no repeated entries.
   --
   -- The pile is ordered according to the Dictionary.Declared_Before
   -- relation on Symbols, so that iterating over the content of a Pile
   -- yields the Symbols in that order.
   ---------------------------------------------------------------------

   procedure Obtain (Heap : in out Cells.Heap_Record;
                     Node :    out Cells.Cell);
   --# global in out Statistics.TableUsage;
   --# derives Heap,
   --#         Statistics.TableUsage from *,
   --#                                    Heap &
   --#         Node                  from Heap;

   procedure Free (Heap : in out Cells.Heap_Record;
                   Node : in     Cells.Cell);
   --# derives Heap from *,
   --#                   Node;

   procedure SetParent (Heap       : in out Cells.Heap_Record;
                        Node       : in     Cells.Cell;
                        ParentNode : in     Cells.Cell);
   --# derives Heap from *,
   --#                   Node,
   --#                   ParentNode;

   procedure SetSibling (Heap        : in out Cells.Heap_Record;
                         Node        : in     Cells.Cell;
                         SiblingNode : in     Cells.Cell);
   --# derives Heap from *,
   --#                   Node,
   --#                   SiblingNode;

   -- Some Nodes in the Pile have a DAG associated with them.
   -- This is used, for example, to store the DAG associated
   -- with the initializing aggregate of a composite constant.
   procedure SetDAG (Heap    : in out Cells.Heap_Record;
                     Node    : in     Cells.Cell;
                     DAGNode : in     Cells.Cell);
   --# derives Heap from *,
   --#                   DAGNode,
   --#                   Node;

   procedure SetNodeSymbol (Heap   : in out Cells.Heap_Record;
                            Node   : in     Cells.Cell;
                            Symbol : in     Dictionary.Symbol);
   --# derives Heap from *,
   --#                   Node,
   --#                   Symbol;

   --  Inserts Symbol with DAG into the pile.  If Symbol is already
   --  present, then no action.  The "Declared_Before" ordering
   --  of the Pile is maintained.
   procedure Insert
     (Heap   : in out Cells.Heap_Record;
      Symbol : in     Dictionary.Symbol;
      DAG    : in     Cells.Cell;
      Node   : in out Cells.Cell);
   --# global in out Statistics.TableUsage;
   --# derives Heap                  from *,
   --#                                    DAG,
   --#                                    Node,
   --#                                    Symbol &
   --#         Node,
   --#         Statistics.TableUsage from *,
   --#                                    Heap,
   --#                                    Node,
   --#                                    Symbol;

   --  Determine if Symbol is already in the pile
   function Contains
     (Heap   : in Cells.Heap_Record;
      Symbol : in Dictionary.Symbol;
      Node   : in Cells.Cell)
     return   Boolean;

   function IsNull (Node : Cells.Cell) return Boolean;

   function Parent (Heap : Cells.Heap_Record;
                    Node : Cells.Cell) return Cells.Cell;

   function Sibling (Heap : Cells.Heap_Record;
                     Node : Cells.Cell) return Cells.Cell;

   function DAG (Heap : Cells.Heap_Record;
                 Node : Cells.Cell) return Cells.Cell;

   function NodeSymbol (Heap : Cells.Heap_Record;
                        Node : Cells.Cell) return Dictionary.Symbol;

   -------------------------------------------------------
   -- Assertion Checking and Debugging subprograms
   -------------------------------------------------------

   --  Print a Pile starting at Node in textual format
   --  to Standard_Output
   procedure PrintPile (Heap : Cells.Heap_Record;
                        Node : Cells.Cell);
   --# derives null from Heap,
   --#                   Node;

   --  Returns True iff the Pile starting at Node is in
   --  order given by Dictionary.Declared_Before over the Symbol
   --  field of each node.
   function OrderOK (Heap : Cells.Heap_Record;
                     Node : Cells.Cell) return Boolean;

end Pile;
