-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================
--------------------------------------------------------------------------------
--  Cell_Storage
--
--  Purpose:
--    This pakcage supports the Cells package, proving an abstraction
--    of an automatically-extending array of Cell_Content indexed
--    by the type Cell.
--
--    In the past, the Examiner used a fixed-size array 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 Dictionary;
with LexTokenManager;
with SP_Symbols;
with SPARK.Ada.Containers;

--# inherit Dictionary,
--#         ExaminerConstants,
--#         LexTokenManager,
--#         SPARK.Ada.Containers,
--#         SP_Symbols;

package Cell_Storage is
   -------------------------------------------------------------
   --  Cell Kinds and Attributes
   --
   --  At this level, the Cell Heap is essentially polymorphic and
   --  weakly-typed - each Cell has various attributes whose
   --  usage varies depending on the "Kind" of a Cell.
   --
   --  Cells have a "Kind" (corresponding to the Discriminant
   --  or Tag if we were able to use discriminated records or
   --  tagged types here).  The Kind of a Cell determines which
   --  operations are available and the meaning of other
   --  attributes.
   -------------------------------------------------------------

   type Cell_Kind is (
                      Named_Const,
                      Manifest_Const,
                      Attrib_Value,
                      Attrib_Function,
                      Pending_Function,
                      Declared_Function,
                      Aggregate_Counter,
                      Proof_Function,
                      Field_Access_Function,
                      Field_Update_Function,
                      Element_Function,
                      Update_Function,
                      Succ_Function,
                      Pred_Function,
                      Incomplete_Aggregate,
                      Mk_Aggregate,
                      List_Function,
                      Abs_Function,
                      Trunc_Function,
                      FDL_Div_Op,
                      Procedure_Export,
                      Procedure_Name,
                      Call_Counter,
                      Bitwise_Op,
                      Modified_Op, -- Assignment
                      Op,
                      Reference, -- R-Value of variable
                      Fixed_Var,
                      Return_Var,
                      Root_Integer,
                      Unconstrained_Attribute_Prefix, -- usedfor U'xxx where U is an unconstrained object
                      Constraining_Index, -- gives the index for a constrained subtype of uncon obj
                      Function_Call_In_Proof_Context,
                      Proof_Function_Obtain_Precondition,
                      Proof_Function_Obtain_Return,
                      Proof_Function_Syntax_Node,
                      Quantifier,
                      --  Used to stash naturals in a cell, only used for stacks,
                      --  etc. For example see DAG.Build_Annotation_Expression,
                      --  Create_Saved_Context_DAG where we use this to stash the 'val
                      --  of an enum (the loop direction).
                      Internal_Natural,
                      --  Used to stash Dictionary.Scopes in a cell. The scope is
                      --  broken down in to the unit (which is stored in the
                      --  Dictionary.Symbol field) and the visibility (which is stored
                      --  via 'pos in the natural field).
                      Internal_Scope,
                      Unknown_Kind);

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

   -----------------------------------------------------------
   -- Cells have a "rank" attribute, which may be used to
   -- establish a partial ordering of cells.  This is used,
   -- for example, in Declarations, where the rank is used to
   -- produce declaration-before-use order in the FDL
   -- declarations
   -----------------------------------------------------------
   type Cell_Rank is new Short_Integer range 0 .. 32767;

   type Cell_Content is record
      A_Ptr, B_Ptr, C_Ptr, Copy : Cell;
      Lex_Str                   : LexTokenManager.Lex_String;
      Val                       : Natural;
      Assoc_Var                 : Dictionary.Symbol;
      Op_Symbol                 : SP_Symbols.SP_Symbol;
      Rank                      : Cell_Rank;
      Kind                      : Cell_Kind;
      Free                      : Boolean;
      Marked                    : Boolean;
   end record;
   pragma Pack (Cell_Content);

   -- Vector is an automatcially-extending array of Cell_Content
   type Vector is private;

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

   function Last_Index (V : Vector) return Cell;

   function Get_Element (V     : in Vector;
                         Index : in Cell) return Cell_Content;

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

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

private
   --# hide Cell_Storage;

   package Vectors is new Ada.Containers.Vectors (Index_Type   => Cell,
                                                  Element_Type => Cell_Content);

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

end Cell_Storage;
