-------------------------------------------------------------------------------
-- (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 SystemErrors;

separate (Declarations)
procedure OutputDeclarations
  (Heap        : in out Cells.Heap_Record;
   File        : in     SPARK_IO.File_Type;
   Rule_File   : in     SPARK_IO.File_Type;
   Scope       : in     Dictionary.Scopes;
   Write_Rules : in     Boolean;
   EndPosition : in     LexTokenManager.Token_Position)
is
   NeededSymbols : Cells.Cell;

   ---------------------------------------------------------------------

   function IsLocalOwnVariableWithRefinement (Sym   : Dictionary.Symbol;
                                              Scope : Dictionary.Scopes) return Boolean
   --# global in Dictionary.Dict;
   is
      Result : Boolean;
   begin
      if Dictionary.IsOwnVariable (Sym) then
         if Dictionary.OwnVariableHasType (Sym, Scope) then
            -- it has a concrete type so it can't be what we are looking for
            Result := False;
         else
            -- it may be what we are looking for; see if it is local to this package
            Result :=
              Dictionary.Packages_Are_Equal
              (Left_Symbol  => Dictionary.GetOwner (Sym),
               Right_Symbol => Dictionary.GetEnclosingPackage (Scope));
         end if;
      else
         Result := False;
      end if;
      return Result;
   end IsLocalOwnVariableWithRefinement;

   ---------------------------------------------------------------------

   procedure GenerateDeclarations
     (Heap          : in out Cells.Heap_Record;
      UsedSymbols   : in     Cells.Cell;
      Scope         : in     Dictionary.Scopes;
      NeededSymbols :    out Cells.Cell)
   --# global in     AttributeList;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in out Statistics.TableUsage;
   --# derives Heap,
   --#         Statistics.TableUsage from *,
   --#                                    AttributeList,
   --#                                    Dictionary.Dict,
   --#                                    Heap,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    UsedSymbols &
   --#         NeededSymbols         from AttributeList,
   --#                                    Dictionary.Dict,
   --#                                    Heap,
   --#                                    LexTokenManager.State,
   --#                                    Scope,
   --#                                    UsedSymbols;
      is separate;

   ---------------------------------------------------------------------

   procedure PrintDeclarations
     (Heap           : in out Cells.Heap_Record;
      File           : in     SPARK_IO.File_Type;
      Rule_File      : in     SPARK_IO.File_Type;
      Needed_Symbols : in     Cells.Cell;
      Scope          : in     Dictionary.Scopes;
      Write_Rules    : in     Boolean;
      End_Position   : in     LexTokenManager.Token_Position)
   --# global in     AttributeList;
   --#        in     BitwiseOpList;
   --#        in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in     ProcedureExportList;
   --#        in     ReturnSymbol;
   --#        in     RootIntegerUsed;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --# derives ErrorHandler.Error_Context from *,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         End_Position,
   --#                                         File,
   --#                                         Heap,
   --#                                         LexTokenManager.State,
   --#                                         Needed_Symbols,
   --#                                         Rule_File,
   --#                                         Scope,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Write_Rules &
   --#         Heap,
   --#         Statistics.TableUsage      from *,
   --#                                         Dictionary.Dict,
   --#                                         Heap,
   --#                                         Needed_Symbols,
   --#                                         Scope,
   --#                                         Write_Rules &
   --#         SPARK_IO.File_Sys          from *,
   --#                                         AttributeList,
   --#                                         BitwiseOpList,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         End_Position,
   --#                                         ErrorHandler.Error_Context,
   --#                                         File,
   --#                                         Heap,
   --#                                         LexTokenManager.State,
   --#                                         Needed_Symbols,
   --#                                         ProcedureExportList,
   --#                                         ReturnSymbol,
   --#                                         RootIntegerUsed,
   --#                                         Rule_File,
   --#                                         Scope,
   --#                                         Write_Rules;
      is separate;

begin -- OutputDeclarations

   if Pile.OrderOK (Heap, UsedSymbols) then
      --Debug.PrintMsg ("UsedSymbols order OK", True);
      null;
   else
      --Debug.PrintMsg ("Dump of UsedSymbols before GenerateDeclarations", True);
      Pile.PrintPile (Heap, UsedSymbols);
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Assertion_Failure,
         Msg     => "UsedSymbols before GenerateDeclarations not in order");
   end if;

   GenerateDeclarations (Heap, UsedSymbols, Scope, NeededSymbols);

   if Pile.OrderOK (Heap, NeededSymbols) then
      --Debug.PrintMsg ("NeededSymbols order OK", True);
      null;
   else
      --Debug.PrintMsg ("Dump of NeededSymbols after GenerateDeclarations", True);
      Pile.PrintPile (Heap, NeededSymbols);
      SystemErrors.Fatal_Error
        (Sys_Err => SystemErrors.Assertion_Failure,
         Msg     => "NeededSymbols after GenerateDeclarations not in order");
   end if;

   PrintDeclarations (Heap, File, Rule_File, NeededSymbols, Scope, Write_Rules, EndPosition);
end OutputDeclarations;
