-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================
--------------------------------------------------------------------------------
--  Heap_Storage
--
--  Purpose:
--    This pakcage supports the Heap package, proving an abstraction
--    of an automatically-extending array of Atom_Descriptors, indexed
--    by the type Atom.
--
--    In the past, the Examiner used a fixed-size array in Heap to
--    offer this abstraction, but this had the drawback of a fixed
--    capacity.  This package, introduced in Release 10.1 solves
--    that by offering an implementation where the Vector automatically
--    extends its capacity as required.
--
-- Implementation
--    Uses Ada.Containers.Vectors in the (hidden) private part and
--    body.
--------------------------------------------------------------------------------

with Ada.Containers;
with Ada.Containers.Vectors;
with SPARK.Ada.Containers;

--# inherit SPARK.Ada.Containers;

package Heap_Storage is
   type Atom is range 0 .. SPARK.Ada.Containers.Count_Type'Last;
   --# assert Atom'Base is Integer;

   type Vector is private;

   Empty_Vector : constant Vector;

   type Atom_Descriptor is record
      ValueA, ValueB     : Natural;
      PointerA, PointerB : Atom;
   end record;

   procedure Initialize (Initial_Length : in     SPARK.Ada.Containers.Count_Type;
                         V              :    out Vector);
   --# derives V from Initial_Length;

   function Last_Index (V : Vector) return Atom;

   function Get_Element (V     : in Vector;
                         Index : in Atom) return Atom_Descriptor;

   procedure Set_Element (V     : in out Vector;
                          Index : in     Atom;
                          Value : in     Atom_Descriptor);
   --# derives V from *,
   --#                Index,
   --#                Value;

   -- Appends Value to V, extending the capacity of V if necessary
   procedure Append (V     : in out Vector;
                     Value : in     Atom_Descriptor);
   --# derives V from *,
   --#                Value;

private
   --# hide Heap_Storage;

   package Vectors is new Ada.Containers.Vectors (Index_Type   => Atom,
                                                  Element_Type => Atom_Descriptor);

   type Vector is record
      Vec : Vectors.Vector;
   end record;

   Empty_Vector : constant Vector := Vector'(Vec => Vectors.Empty_Vector);

end Heap_Storage;
