-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

separate (Dictionary)
procedure Add_Use_Type_Reference
  (The_Visibility : in Visibility;
   The_Unit       : in Symbol;
   Type_Mark      : in RawDict.Type_Info_Ref;
   Comp_Unit      : in ContextManager.UnitDescriptors;
   Declaration    : in Location) is
   The_Generic_Unit    : RawDict.Generic_Unit_Info_Ref;
   The_Use_Type_Clause : RawDict.Use_Type_Clause_Info_Ref;

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

   procedure Add_Use_Type_Clause (Type_Mark   : in RawDict.Type_Info_Ref;
                                  Declaration : in Location)
   --# global in     Dict;
   --#        in     LexTokenManager.State;
   --#        in out SPARK_IO.File_Sys;
   --# derives SPARK_IO.File_Sys from *,
   --#                                Declaration,
   --#                                Dict,
   --#                                LexTokenManager.State,
   --#                                Type_Mark;
   is
   begin
      if SPARK_IO.Is_Open (Dict.TemporaryFile) then
         Write_String (Dict.TemporaryFile, "use type clause of ");
         Write_Name (File => Dict.TemporaryFile,
                     Item => RawDict.Get_Type_Symbol (Type_Mark));
         Write_String (Dict.TemporaryFile, " is at ");
         Write_Location (File => Dict.TemporaryFile,
                         Loc  => Declaration);
         Write_Line (Dict.TemporaryFile, " ;");
      end if;
   end Add_Use_Type_Clause;

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

   procedure Add_Package_Visible_Use_Type_Reference
     (The_Use_Type_Clause : in RawDict.Use_Type_Clause_Info_Ref;
      The_Package         : in RawDict.Package_Info_Ref)
   --# global in out Dict;
   --# derives Dict from *,
   --#                   The_Package,
   --#                   The_Use_Type_Clause;
   is
   begin
      RawDict.Set_Next_Use_Type_Clause
        (The_Use_Type_Clause => The_Use_Type_Clause,
         Next                => RawDict.Get_Package_Visible_Use_Type_Clauses (The_Package => The_Package));
      RawDict.Set_Package_Visible_Use_Type_Clauses (The_Package         => The_Package,
                                                    The_Use_Type_Clause => The_Use_Type_Clause);
   end Add_Package_Visible_Use_Type_Reference;

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

   procedure Add_Package_Local_Use_Type_Reference
     (The_Use_Type_Clause : in RawDict.Use_Type_Clause_Info_Ref;
      The_Package         : in RawDict.Package_Info_Ref)
   --# global in out Dict;
   --# derives Dict from *,
   --#                   The_Package,
   --#                   The_Use_Type_Clause;
   is
   begin
      RawDict.Set_Next_Use_Type_Clause
        (The_Use_Type_Clause => The_Use_Type_Clause,
         Next                => RawDict.Get_Package_Local_Use_Type_Clauses (The_Package => The_Package));
      RawDict.Set_Package_Local_Use_Type_Clauses (The_Package         => The_Package,
                                                  The_Use_Type_Clause => The_Use_Type_Clause);
   end Add_Package_Local_Use_Type_Reference;

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

   procedure Add_Protected_Type_Use_Type_Reference
     (The_Use_Type_Clause : in RawDict.Use_Type_Clause_Info_Ref;
      The_Protected_Type  : in RawDict.Type_Info_Ref)
   --# global in out Dict;
   --# derives Dict from *,
   --#                   The_Protected_Type,
   --#                   The_Use_Type_Clause;
   is
   begin
      RawDict.Set_Next_Use_Type_Clause
        (The_Use_Type_Clause => The_Use_Type_Clause,
         Next                => RawDict.Get_Protected_Type_Use_Type_Clauses (The_Protected_Type => The_Protected_Type));
      RawDict.Set_Protected_Type_Use_Type_Clauses
        (The_Protected_Type  => The_Protected_Type,
         The_Use_Type_Clause => The_Use_Type_Clause);
   end Add_Protected_Type_Use_Type_Reference;

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

   procedure Add_Task_Type_Use_Type_Reference
     (The_Use_Type_Clause : in RawDict.Use_Type_Clause_Info_Ref;
      The_Task_Type       : in RawDict.Type_Info_Ref)
   --# global in out Dict;
   --# derives Dict from *,
   --#                   The_Task_Type,
   --#                   The_Use_Type_Clause;
   is
   begin
      RawDict.Set_Next_Use_Type_Clause
        (The_Use_Type_Clause => The_Use_Type_Clause,
         Next                => RawDict.Get_Task_Type_Use_Type_Clauses (The_Task_Type => The_Task_Type));
      RawDict.Set_Task_Type_Use_Type_Clauses (The_Task_Type       => The_Task_Type,
                                              The_Use_Type_Clause => The_Use_Type_Clause);
   end Add_Task_Type_Use_Type_Reference;

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

   procedure Add_Subprogram_Use_Type_Reference
     (The_Use_Type_Clause : in RawDict.Use_Type_Clause_Info_Ref;
      The_Subprogram      : in RawDict.Subprogram_Info_Ref)
   --# global in out Dict;
   --# derives Dict from *,
   --#                   The_Subprogram,
   --#                   The_Use_Type_Clause;
   is
   begin
      RawDict.Set_Next_Use_Type_Clause
        (The_Use_Type_Clause => The_Use_Type_Clause,
         Next                => RawDict.Get_Subprogram_Use_Type_Clauses (The_Subprogram => The_Subprogram));
      RawDict.Set_Subprogram_Use_Type_Clauses (The_Subprogram      => The_Subprogram,
                                               The_Use_Type_Clause => The_Use_Type_Clause);
   end Add_Subprogram_Use_Type_Reference;

begin -- Add_Use_Type_Reference
   Add_Use_Type_Clause (Type_Mark   => Type_Mark,
                        Declaration => Declaration);
   RawDict.Create_Use_Type_Clause
     (Type_Mark           => Type_Mark,
      Comp_Unit           => Comp_Unit,
      Loc                 => Declaration.Start_Position,
      The_Use_Type_Clause => The_Use_Type_Clause);

   case The_Visibility is
      when Visible | Privat =>
         case RawDict.GetSymbolDiscriminant (The_Unit) is
            when Package_Symbol =>
               Add_Package_Visible_Use_Type_Reference
                 (The_Use_Type_Clause => The_Use_Type_Clause,
                  The_Package         => RawDict.Get_Package_Info_Ref (Item => The_Unit)); -- GAA External
            when Generic_Unit_Symbol =>
               The_Generic_Unit := RawDict.Get_Generic_Unit_Info_Ref (Item => The_Unit); -- GAA External
               case RawDict.Get_Generic_Unit_Kind (The_Generic_Unit => The_Generic_Unit) is
                  when Generic_Of_Package =>
                     Add_Package_Visible_Use_Type_Reference
                       (The_Use_Type_Clause => The_Use_Type_Clause,
                        The_Package         => RawDict.Get_Generic_Unit_Owning_Package (The_Generic_Unit => The_Generic_Unit));
                  when Generic_Of_Subprogram =>
                     Add_Subprogram_Use_Type_Reference
                       (The_Use_Type_Clause => The_Use_Type_Clause,
                        The_Subprogram      => RawDict.Get_Generic_Unit_Owning_Subprogram (The_Generic_Unit => The_Generic_Unit));
               end case;
            when others => -- non-exec code
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                  Msg     => "in Dictionary.Add_Use_Type_Reference");
         end case;
      when Local =>
         case RawDict.GetSymbolDiscriminant (The_Unit) is
            when Package_Symbol =>
               Add_Package_Local_Use_Type_Reference
                 (The_Use_Type_Clause => The_Use_Type_Clause,
                  The_Package         => RawDict.Get_Package_Info_Ref (Item => The_Unit)); -- GAA External
            when Subprogram_Symbol =>
               Add_Subprogram_Use_Type_Reference
                 (The_Use_Type_Clause => The_Use_Type_Clause,
                  The_Subprogram      => RawDict.Get_Subprogram_Info_Ref (Item => The_Unit)); -- GAA External
            when Type_Symbol =>
               case RawDict.Get_Type_Discriminant (Type_Mark => RawDict.Get_Type_Info_Ref (Item => The_Unit)) is -- GAA External
                  when Protected_Type_Item =>
                     Add_Protected_Type_Use_Type_Reference
                       (The_Use_Type_Clause => The_Use_Type_Clause,
                        The_Protected_Type  => RawDict.Get_Type_Info_Ref (Item => The_Unit)); -- GAA External
                  when Task_Type_Item =>
                     Add_Task_Type_Use_Type_Reference
                       (The_Use_Type_Clause => The_Use_Type_Clause,
                        The_Task_Type       => RawDict.Get_Type_Info_Ref (Item => The_Unit)); -- GAA External
                  when others => -- non-exec code
                     SystemErrors.Fatal_Error
                       (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                        Msg     => "in Dictionary.Add_Use_Type_Reference");
               end case;
            when others => -- non-exec code
               SystemErrors.Fatal_Error
                 (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                  Msg     => "in Dictionary.Add_Use_Type_Reference");
         end case;
   end case;
   AddOtherReference (RawDict.Get_Type_Symbol (Type_Mark), The_Unit, Declaration);
end Add_Use_Type_Reference;
