-------------------------------------------------------------------------------
-- (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)
function GetScope (Item : Symbol) return Scopes is
   Scope      : Scopes;
   Item_Local : Symbol;

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

   function Get_Implicit_Proof_Function_Scope (Proof_Function : Symbol) return Scopes
   --# global in Dict;
   is
      Ada_Function : RawDict.Subprogram_Info_Ref;
      Scope        : Scopes;
   begin
      Ada_Function := RawDict.GetImplicitProofFunctionAdaFunction (Proof_Function);
      Scope        :=
        RawDict.Get_Declaration_Scope (The_Declaration => RawDict.Get_Subprogram_Specification (The_Subprogram => Ada_Function));
      if RawDict.Get_Subprogram_Implicit_Proof_Function (The_Subprogram => Ada_Function,
                                                         Abstraction    => IsRefined) =
        Proof_Function then
         Scope := GetLocalScope (Scope);
      end if;
      return Scope;
   end Get_Implicit_Proof_Function_Scope;

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

   function Get_Subprogram_Parameter_Scope (The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Local,
         The_Unit       => RawDict.Get_Subprogram_Symbol
           (RawDict.Get_Subprogram_Parameter_Subprogram (The_Subprogram_Parameter => The_Subprogram_Parameter)));
   end Get_Subprogram_Parameter_Scope;

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

   function Get_Parameter_Constraint_Scope (The_Parameter_Constraint : RawDict.Parameter_Constraint_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Get_Subprogram_Parameter_Scope
        (The_Subprogram_Parameter => RawDict.Get_Parameter_Constraint_Subprogram_Parameter (The_Parameter_Constraint => The_Parameter_Constraint));
   end Get_Parameter_Constraint_Scope;

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

   function Get_Generic_Parameter_Scope (The_Generic_Parameter : RawDict.Generic_Parameter_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Local,
         The_Unit       => RawDict.Get_Generic_Unit_Symbol
           (RawDict.Get_Generic_Parameter_Owning_Generic (The_Generic_Parameter => The_Generic_Parameter)));
   end Get_Generic_Parameter_Scope;

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

   function Get_Generic_Unit_Scope (The_Generic_Unit : RawDict.Generic_Unit_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return RawDict.Get_Generic_Unit_Scope (The_Generic_Unit => The_Generic_Unit);
   end Get_Generic_Unit_Scope;

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

   function Get_Implicit_Return_Variable_Scope
     (The_Implicit_Return_Variable : RawDict.Implicit_Return_Variable_Info_Ref)
     return                         Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Local,
         The_Unit       => RawDict.Get_Subprogram_Symbol
           (RawDict.Get_Implicit_Return_Variable_Function
              (The_Implicit_Return_Variable => The_Implicit_Return_Variable)));
   end Get_Implicit_Return_Variable_Scope;

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

   function Get_Quantified_Variable_Scope (The_Quantified_Variable : RawDict.Quantified_Variable_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Local,
         The_Unit       => RawDict.Get_Quantified_Variable_Region (The_Quantified_Variable => The_Quantified_Variable));
   end Get_Quantified_Variable_Scope;

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

   function Get_Loop_Scope (The_Loop : Symbol) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility (The_Visibility => Local,
                             The_Unit       => RawDict.GetLoopRegion (The_Loop));
   end Get_Loop_Scope;

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

   function Get_Loop_Parameter_Scope (The_Parameter : Symbol) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility (The_Visibility => Local,
                             The_Unit       => RawDict.GetLoopParameterLoop (The_Parameter));
   end Get_Loop_Parameter_Scope;

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

   function Get_Enumeration_Literal_Scope (The_Enumeration_Literal : RawDict.Enumeration_Literal_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return RawDict.Get_Declaration_Scope
        (The_Declaration => Get_Type_Declaration
           (Type_Mark => RawDict.Get_Enumeration_Literal_Type (The_Enumeration_Literal => The_Enumeration_Literal)));
   end Get_Enumeration_Literal_Scope;

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

   function Get_Record_Component_Scope (The_Record_Component : RawDict.Record_Component_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Local,
         The_Unit       => RawDict.Get_Type_Symbol
           (RawDict.Get_Record_Component_Record_Type (The_Record_Component => The_Record_Component)));
   end Get_Record_Component_Scope;

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

   function Get_Known_Discriminant_Scope (The_Discriminant : Symbol) return Scopes
   --# global in Dict;
   is
   begin
      return Set_Visibility
        (The_Visibility => Visible,
         The_Unit       => RawDict.Get_Type_Symbol (RawDict.GetDiscriminantProtectedType (The_Discriminant)));
   end Get_Known_Discriminant_Scope;

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

   function Get_Constituent_Scope (The_Constituent : RawDict.Constituent_Info_Ref) return Scopes
   --# global in Dict;
   is
   begin
      return Get_Variable_Scope (The_Variable => RawDict.Get_Constituent_Variable (The_Constituent => The_Constituent));
   end Get_Constituent_Scope;

begin -- GetScope
   Item_Local := Item;
   -- if the symbol is a special on loop entry variable we use the original variable
   -- to determine whether a prefix is needed
   if RawDict.GetSymbolDiscriminant (Item_Local) = LoopEntryVariableSymbol then
      Item_Local := RawDict.GetLoopEntryVariableOriginalVar (Item_Local);
   end if;

   -- Useful statements for investigating an InvalidGetScopeRequest failure
   -- Debug.PrintMsg ("Discriminant on entry to GetScope case statement is ", False);
   -- Debug.PrintMsg (SymbolDiscriminant'Image (RawDict.GetSymbolDiscriminant (Item_Local)), True);

   case RawDict.GetSymbolDiscriminant (Item_Local) is
      when Type_Symbol =>
         Scope := Get_Type_Scope (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item_Local));
      when Constant_Symbol =>
         Scope := Get_Constant_Scope (The_Constant => RawDict.Get_Constant_Info_Ref (Item => Item_Local));
      when Subprogram_Symbol =>
         Scope := Get_Subprogram_Scope (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Item_Local));
      when Package_Symbol =>
         Scope := Get_Package_Scope (The_Package => RawDict.Get_Package_Info_Ref (Item => Item_Local));
      when ImplicitProofFunctionSymbol =>
         Scope := Get_Implicit_Proof_Function_Scope (Proof_Function => Item_Local);
      when Subprogram_Parameter_Symbol =>
         Scope :=
           Get_Subprogram_Parameter_Scope
           (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (Item => Item_Local));
      when Parameter_Constraint_Symbol =>
         Scope :=
           Get_Parameter_Constraint_Scope
           (The_Parameter_Constraint => RawDict.Get_Parameter_Constraint_Info_Ref (Item => Item_Local));
      when Generic_Parameter_Symbol =>
         Scope := Get_Generic_Parameter_Scope (The_Generic_Parameter => RawDict.Get_Generic_Parameter_Info_Ref (Item => Item_Local));
      when Generic_Unit_Symbol =>
         Scope := Get_Generic_Unit_Scope (The_Generic_Unit => RawDict.Get_Generic_Unit_Info_Ref (Item => Item_Local));
      when Implicit_Return_Variable_Symbol =>
         Scope :=
           Get_Implicit_Return_Variable_Scope
           (The_Implicit_Return_Variable => RawDict.Get_Implicit_Return_Variable_Info_Ref (Item => Item_Local));
      when Variable_Symbol =>
         Scope := Get_Variable_Scope (The_Variable => RawDict.Get_Variable_Info_Ref (Item => Item_Local));
      when Quantified_Variable_Symbol =>
         Scope :=
           Get_Quantified_Variable_Scope (The_Quantified_Variable => RawDict.Get_Quantified_Variable_Info_Ref (Item => Item_Local));
      when LoopSymbol =>
         Scope := Get_Loop_Scope (The_Loop => Item_Local);
      when LoopParameterSymbol =>
         Scope := Get_Loop_Parameter_Scope (The_Parameter => Item_Local);
      when Enumeration_Literal_Symbol =>
         Scope :=
           Get_Enumeration_Literal_Scope (The_Enumeration_Literal => RawDict.Get_Enumeration_Literal_Info_Ref (Item => Item_Local));
      when Record_Component_Symbol =>
         Scope := Get_Record_Component_Scope (The_Record_Component => RawDict.Get_Record_Component_Info_Ref (Item => Item_Local));
      when KnownDiscriminantSymbol =>
         Scope := Get_Known_Discriminant_Scope (The_Discriminant => Item_Local);
      when Constituent_Symbol =>
         Scope := Get_Constituent_Scope (The_Constituent => RawDict.Get_Constituent_Info_Ref (Item => Item_Local));
      when others => -- non-exec code
         Scope := NullScope;
         SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                                   Msg     => "in Dictionary.GetScope");
   end case;
   return Scope;
end GetScope;
