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

use type Dictionary.Symbol;
use type ExaminerConstants.RefType;
use type LexTokenManager.Str_Comp_Result;

--# inherit Dictionary,
--#         ExaminerConstants,
--#         LexTokenManager;

package Lists is
   type List_Heap is private;
   type List is private;
   Null_List : constant List;

   procedure Init (Heap : out List_Heap);
   --# derives Heap from ;

   procedure New_List (Heap     : in out List_Heap;
                       The_List :    out List;
                       OK       :    out Boolean);
   --# derives Heap,
   --#         OK,
   --#         The_List from Heap;

   procedure Add_Name
     (Heap            : in out List_Heap;
      The_List        : in     List;
      Name            : in     LexTokenManager.Lex_String;
      Already_Present :    out Boolean;
      Ok              :    out Boolean);
   --# global in LexTokenManager.State;
   --# derives Already_Present,
   --#         Heap,
   --#         Ok              from Heap,
   --#                              LexTokenManager.State,
   --#                              Name,
   --#                              The_List;

   procedure Add_Symbol
     (Heap            : in out List_Heap;
      The_List        : in     List;
      Symbol          : in     Dictionary.Symbol;
      Already_Present :    out Boolean;
      Ok              :    out Boolean);
   --# global in LexTokenManager.State;
   --# derives Already_Present,
   --#         Heap,
   --#         Ok              from Heap,
   --#                              LexTokenManager.State,
   --#                              Symbol,
   --#                              The_List;

   procedure Get_First
     (Heap     : in out List_Heap;
      The_List : in out List;
      Symbol   :    out Dictionary.Symbol;
      Empty    :    out Boolean;
      Ok       :    out Boolean);
   --# global in LexTokenManager.State;
   --# derives Empty,
   --#         Heap,
   --#         Ok,
   --#         Symbol,
   --#         The_List from Heap,
   --#                       LexTokenManager.State,
   --#                       The_List;
   -- Removes head of list and returns it.  Ok is false if list illegal.
   -- Empty is true if no value to retieve.
   -- List changes as a result of call but is never deleted even when empty.

   procedure Delete_List (Heap     : in out List_Heap;
                          The_List : in out List);
   --# global in LexTokenManager.State;
   --# derives Heap     from *,
   --#                       LexTokenManager.State,
   --#                       The_List &
   --#         The_List from ;

   function Is_Member
     (Heap     : List_Heap;
      The_List : List;
      Str      : LexTokenManager.Lex_String)
     return     Boolean;
   --# global in LexTokenManager.State;

private
   type List is range 0 .. ExaminerConstants.ListsHeapSize;
   --# assert List'Base is Integer; -- for the "Large" Examiner

   type Heap_Element is record
      -- case ??? is
      --    when ??? =>
      Name : LexTokenManager.Lex_String;
      --    when ??? =>
      Symbol : Dictionary.Symbol;
      -- end case;
      Next : List;
   end record;

   type Heap_Arrays is array (List) of Heap_Element;

   type List_Heap is record
      Heap_Array : Heap_Arrays;
      High_Mark  : List;
      First_Free : List;
   end record;

   Null_List : constant List := 0;
end Lists;
