-------------------------------------------------------------------------------
-- (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 NextSymbol (Previous : Iterator) return Iterator is
   Next : Iterator;

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

   function Next_Declarative_Item (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol   := NullSymbol;
      Found           : Boolean  := False;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref and then not Found loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         case RawDict.GetSymbolDiscriminant (Item) is
            when Package_Symbol =>
               Found := The_Declaration /= RawDict.Get_Package_Body (The_Package => RawDict.Get_Package_Info_Ref (Item => Item));
            when Subprogram_Symbol =>
               Found := The_Declaration /=
                 RawDict.Get_Subprogram_Body (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Item));
            when others =>
               Found := True;
         end case;
         if not Found then
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;

      if The_Declaration /= RawDict.Null_Declaration_Info_Ref then
         Next :=
           Iterator'
           (DeclarativeItemIterator,
            IsAbstract,
            Item,
            RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
      end if;
      return Next;
   end Next_Declarative_Item;

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

   function Next_Deferred_Constant (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Constant_Symbol
           and then Constant_Is_Deferred (The_Constant => RawDict.Get_Constant_Info_Ref (Item => Item)) then
            Next            :=
              Iterator'
              (DeferredConstantIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Deferred_Constant;

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

   function Next_Array_Index (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Array_Index : RawDict.Array_Index_Info_Ref;
      Result          : Iterator := NullIterator;
   begin
      The_Array_Index := RawDict.Get_Next_Array_Index (RawDict.Get_Array_Index_Info_Ref (Previous.Context));
      if The_Array_Index /= RawDict.Null_Array_Index_Info_Ref then
         Result :=
           Iterator'
           (ArrayIndexIterator,
            IsAbstract,
            RawDict.Get_Type_Symbol (RawDict.Get_Array_Index_Type (The_Array_Index => The_Array_Index)),
            RawDict.Get_Array_Index_Symbol (The_Array_Index));
      end if;
      return Result;
   end Next_Array_Index;

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

   function Next_Loop (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Loop : Symbol;
      Next     : Iterator;
   begin
      The_Loop := RawDict.GetNextLoop (CurrentSymbol (Previous));
      if The_Loop = NullSymbol then
         Next := NullIterator;
      else
         Next := Iterator'(LoopIterator, IsAbstract, The_Loop, NullSymbol);
      end if;
      return Next;
   end Next_Loop;

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

   function Next_Undeclared_Type (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Type_Symbol
           and then Is_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item))
           and then RawDict.Get_Type_Discriminant (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item)) = Unknown_Type_Item then
            Next            :=
              Iterator'
              (UndeclaredTypeIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Undeclared_Type;

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

   function Next_Private_Type (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Type_Symbol
           and then Is_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item))
           and then Type_Is_Private (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item))
           and then RawDict.Get_Declaration_Context (The_Declaration => The_Declaration) = ProgramContext then
            Next            :=
              Iterator'
              (PrivateTypeIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Private_Type;

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

   function Next_Enumeration_Literal (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Enumeration_Literal : RawDict.Enumeration_Literal_Info_Ref;
      Next                    : Iterator := NullIterator;
   begin
      The_Enumeration_Literal :=
        RawDict.Get_Next_Enumeration_Literal
        (The_Enumeration_Literal => RawDict.Get_Enumeration_Literal_Info_Ref (CurrentSymbol (Previous)));
      if The_Enumeration_Literal /= RawDict.Null_Enumeration_Literal_Info_Ref then
         Next :=
           Iterator'
           (EnumerationLiteralIterator,
            IsAbstract,
            RawDict.Get_Enumeration_Literal_Symbol (The_Enumeration_Literal),
            NullSymbol);
      end if;
      return Next;
   end Next_Enumeration_Literal;

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

   function Next_Record_Component (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Record_Component : RawDict.Record_Component_Info_Ref;
      Next                 : Iterator := NullIterator;
   begin
      The_Record_Component :=
        RawDict.Get_Next_Record_Component
        (The_Record_Component => RawDict.Get_Record_Component_Info_Ref (CurrentSymbol (Previous)));
      if The_Record_Component /= RawDict.Null_Record_Component_Info_Ref then
         Next :=
           Iterator'(RecordComponentIterator, IsAbstract, RawDict.Get_Record_Component_Symbol (The_Record_Component), NullSymbol);
      end if;
      return Next;
   end Next_Record_Component;

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

   function Next_Extended_Record_Component (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Record_Component : RawDict.Record_Component_Info_Ref;
      Current_Record       : RawDict.Type_Info_Ref;
      Next                 : Iterator;
   begin
      The_Record_Component :=
        RawDict.Get_Next_Record_Component
        (The_Record_Component => RawDict.Get_Record_Component_Info_Ref (CurrentSymbol (Previous)));
      if The_Record_Component = RawDict.Null_Record_Component_Info_Ref then
         -- current record has no more fields so see if earlier extension has
         Current_Record :=
           Back_Track_Up_Inherit_Chain
           (Start_Sym => RawDict.Get_Type_Info_Ref (Previous.Context),
            Stop_Sym  => RawDict.Get_Record_Component_Record_Type
              (The_Record_Component => RawDict.Get_Record_Component_Info_Ref (CurrentSymbol (Previous))));
         loop
            if Current_Record = RawDict.Null_Type_Info_Ref then
               -- searched entire extended record structure
               Next := NullIterator;
               exit;
            end if;

            -- We have a new extended record to search, we need the _second_ field (to skip Inherit)
            The_Record_Component :=
              RawDict.Get_Next_Record_Component
              (The_Record_Component => RawDict.Get_Type_First_Record_Component (Type_Mark => Current_Record));
            if The_Record_Component /= RawDict.Null_Record_Component_Info_Ref then
               -- found a field
               Next :=
                 Iterator'
                 (ExtendedRecordComponentIterator,
                  IsAbstract,
                  RawDict.Get_Record_Component_Symbol (The_Record_Component),
                  Previous.Context);
               exit;
            end if;

            -- if get here then we must have encountered a null extension - we must backtrack again
            Current_Record :=
              Back_Track_Up_Inherit_Chain (Start_Sym => RawDict.Get_Type_Info_Ref (Previous.Context),
                                           Stop_Sym  => Current_Record);
         end loop;
      else -- record has further fields
         Next :=
           Iterator'
           (ExtendedRecordComponentIterator,
            IsAbstract,
            RawDict.Get_Record_Component_Symbol (The_Record_Component),
            Previous.Context);
      end if;
      return Next;
   end Next_Extended_Record_Component;

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

   function Next_Library_Unit (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol   := NullSymbol;
      Found           : Boolean  := False;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref and then not Found loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         case RawDict.GetSymbolDiscriminant (Item) is
            when Package_Symbol =>
               Found := The_Declaration /= RawDict.Get_Package_Body (The_Package => RawDict.Get_Package_Info_Ref (Item => Item));
            when Subprogram_Symbol =>
               Found := The_Declaration /=
                 RawDict.Get_Subprogram_Body (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Item));
            when others =>
               Found := False;
         end case;
         if not Found then
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      if The_Declaration /= RawDict.Null_Declaration_Info_Ref then
         Next :=
           Iterator'(LibraryUnitIterator, IsAbstract, Item, RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
      end if;
      return Next;
   end Next_Library_Unit;

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

   function Next_Withed_Package (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Context_Clause : RawDict.Context_Clause_Info_Ref;
      Next               : Iterator := NullIterator;
   begin
      The_Context_Clause :=
        RawDict.Get_Next_Context_Clause (The_Context_Clause => RawDict.Get_Context_Clause_Info_Ref (Previous.Context));
      if The_Context_Clause /= RawDict.Null_Context_Clause_Info_Ref then
         case RawDict.Get_Context_Clause_Is_Subprogram (The_Context_Clause => The_Context_Clause) is
            when False =>
               Next :=
                 Iterator'
                 (WithedPackageIterator,
                  IsAbstract,
                  RawDict.Get_Package_Symbol (RawDict.Get_Context_Clause_Package (The_Context_Clause => The_Context_Clause)),
                  RawDict.Get_Context_Clause_Symbol (The_Context_Clause));
            when True =>
               Next :=
                 Iterator'
                 (WithedPackageIterator,
                  IsAbstract,
                  RawDict.Get_Subprogram_Symbol (RawDict.Get_Context_Clause_Subprogram (The_Context_Clause => The_Context_Clause)),
                  RawDict.Get_Context_Clause_Symbol (The_Context_Clause));
         end case;
      end if;
      return Next;
   end Next_Withed_Package;

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

   function Next_Inherited_Package (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Context_Clause : RawDict.Context_Clause_Info_Ref;
      Next               : Iterator := NullIterator;
   begin
      The_Context_Clause :=
        RawDict.Get_Next_Context_Clause (The_Context_Clause => RawDict.Get_Context_Clause_Info_Ref (Previous.Context));
      if The_Context_Clause /= RawDict.Null_Context_Clause_Info_Ref then
         case RawDict.Get_Context_Clause_Is_Subprogram (The_Context_Clause => The_Context_Clause) is
            when False =>
               Next :=
                 Iterator'
                 (InheritedPackageIterator,
                  IsAbstract,
                  RawDict.Get_Package_Symbol (RawDict.Get_Context_Clause_Package (The_Context_Clause => The_Context_Clause)),
                  RawDict.Get_Context_Clause_Symbol (The_Context_Clause));
            when True =>
               Next :=
                 Iterator'
                 (InheritedPackageIterator,
                  IsAbstract,
                  RawDict.Get_Subprogram_Symbol (RawDict.Get_Context_Clause_Subprogram (The_Context_Clause => The_Context_Clause)),
                  RawDict.Get_Context_Clause_Symbol (The_Context_Clause));
         end case;
      end if;
      return Next;
   end Next_Inherited_Package;

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

   function Next_Visible_Or_Private_Subprogram (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Subprogram_Symbol
           and then The_Declaration /=
           RawDict.Get_Subprogram_Body (The_Subprogram => RawDict.Get_Subprogram_Info_Ref (Item => Item)) then
            Next            :=
              Iterator'
              (Previous.Discriminant,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Visible_Or_Private_Subprogram;

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

   function Next_Task_Type (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Type_Symbol
           and then Is_Task_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item)) then
            Next            :=
              Iterator'(TaskTypeIterator, IsAbstract, Item, RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Task_Type;

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

   function Next_Own_Task (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Own_Task : Symbol;
      Next     : Iterator;
   begin
      Own_Task := RawDict.GetNextOwnTask (Previous.Context);
      if Own_Task = NullSymbol then
         Next := NullIterator;
      else
         Next :=
           Iterator'(OwnTaskIterator, IsAbstract, RawDict.Get_Variable_Symbol (RawDict.GetOwnTaskVariable (Own_Task)), Own_Task);
      end if;
      return Next;
   end Next_Own_Task;

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

   function Next_Protected_Type (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         -- filter items to leave just protected types that are actually declared (not just announced)
         if RawDict.GetSymbolDiscriminant (Item) = Type_Symbol
           and then Is_Protected_Type (Type_Mark => RawDict.Get_Type_Info_Ref (Item => Item))
           and then Get_Visibility (Scope => GetScope (Item)) = Visible then
            Next            :=
              Iterator'
              (ProtectedTypeIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Protected_Type;

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

   function Next_Subprogram_Parameter (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Next : Iterator;

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

      function Next_Formal_Parameter (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         ProofFunction            : Symbol;
         Ada_Function             : RawDict.Subprogram_Info_Ref;
         GlobalVariables          : Iterator;
         Next                     : Iterator;
      begin
         The_Subprogram_Parameter :=
           RawDict.Get_Next_Subprogram_Parameter
           (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (CurrentSymbol (Previous)));
         ProofFunction            := Previous.Context;

         if The_Subprogram_Parameter = RawDict.Null_Subprogram_Parameter_Info_Ref then
            if ProofFunction = NullSymbol then
               Next := NullIterator;
            else
               Ada_Function    := RawDict.GetImplicitProofFunctionAdaFunction (ProofFunction);
               GlobalVariables :=
                 First_Subprogram_Global_Variable (The_Subprogram => Ada_Function,
                                                   Abstraction    => Previous.Abstraction);
               if GlobalVariables = NullIterator then
                  Next := NullIterator;
               else
                  Next :=
                    Iterator'
                    (ImplicitProofFunctionGlobalIterator,
                     Previous.Abstraction,
                     CurrentSymbol (GlobalVariables),
                     GlobalVariables.Context);
               end if;
            end if;
         else
            Next :=
              Iterator'
              (Previous.Discriminant,
               Previous.Abstraction,
               RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
               ProofFunction);
         end if;
         return Next;
      end Next_Formal_Parameter;

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

      function Next_Global_Variable (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Global_Variable : RawDict.Global_Variable_Info_Ref;
         Next                : Iterator := NullIterator;
      begin
         The_Global_Variable :=
           RawDict.Get_Next_Global_Variable (The_Global_Variable => RawDict.Get_Global_Variable_Info_Ref (Previous.Context));
         if The_Global_Variable /= RawDict.Null_Global_Variable_Info_Ref then
            case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
               when RawDict.Subprogram_Variable_Item =>
                  Next :=
                    Iterator'
                    (Previous.Discriminant,
                     Previous.Abstraction,
                     RawDict.Get_Variable_Symbol
                       (RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable)),
                     RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
               when RawDict.Subprogram_Parameter_Item =>
                  Next :=
                    Iterator'
                    (Previous.Discriminant,
                     Previous.Abstraction,
                     RawDict.Get_Subprogram_Parameter_Symbol
                       (RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable)),
                     RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
               when others => -- non-exec code
                  Next := NullIterator;
                  SystemErrors.Fatal_Error
                    (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                     Msg     => "in Dictionary.Next_Global_Variable");
            end case;
         end if;
         return Next;
      end Next_Global_Variable;

   begin -- Next_Subprogram_Parameter
      case Previous.Discriminant is
         when SubprogramParameterIterator | ImplicitProofFunctionParameterIterator =>
            Next := Next_Formal_Parameter (Previous => Previous);
         when ImplicitProofFunctionGlobalIterator =>
            Next := Next_Global_Variable (Previous => Previous);
         when others =>
            Next := NullIterator;
      end case;
      return Next;
   end Next_Subprogram_Parameter;

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

   function Next_Global_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Global_Variable : RawDict.Global_Variable_Info_Ref;
      Next                : Iterator := NullIterator;
   begin
      The_Global_Variable :=
        RawDict.Get_Next_Global_Variable (The_Global_Variable => RawDict.Get_Global_Variable_Info_Ref (Previous.Context));
      if The_Global_Variable /= RawDict.Null_Global_Variable_Info_Ref then
         case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
            when RawDict.Subprogram_Variable_Item | RawDict.Task_Type_Variable_Item =>
               Next :=
                 Iterator'
                 (GlobalVariableIterator,
                  IsAbstract,
                  RawDict.Get_Variable_Symbol (RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable)),
                  RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
            when RawDict.Subprogram_Parameter_Item =>
               Next :=
                 Iterator'
                 (GlobalVariableIterator,
                  IsAbstract,
                  RawDict.Get_Subprogram_Parameter_Symbol
                    (RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable)),
                  RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
         end case;
      end if;
      return Next;
   end Next_Global_Variable;

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

   function Next_Local_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if Is_Variable (Item) then
            Next            :=
              Iterator'
              (LocalVariableIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Local_Variable;

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

   function Next_Protected_Element (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      if The_Declaration /= RawDict.Null_Declaration_Info_Ref then
         Next :=
           Iterator'
           (LocalVariableIterator,
            IsAbstract,
            RawDict.Get_Declaration_Item (The_Declaration => The_Declaration),
            RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
      end if;
      return Next;
   end Next_Protected_Element;

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

   function Next_Initialized_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if Is_Variable (Item)
           and then RawDict.Get_Variable_Initialized (The_Variable => RawDict.Get_Variable_Info_Ref (Item)) then
            Next            :=
              Iterator'
              (InitializedVariableIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Initialized_Variable;

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

   function Next_Import_Export (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Next : Iterator;

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

      function Next_Subprogram_Parameter_Import_Export (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         Next                     : Iterator := NullIterator;
         Stop                     : Boolean  := False;
      begin
         The_Subprogram_Parameter :=
           RawDict.Get_Next_Subprogram_Parameter
           (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (CurrentSymbol (Previous)));
         The_Subprogram           :=
           RawDict.Get_Subprogram_Parameter_Subprogram
           (The_Subprogram_Parameter => RawDict.Get_Subprogram_Parameter_Info_Ref (CurrentSymbol (Previous)));

         while The_Subprogram_Parameter /= RawDict.Null_Subprogram_Parameter_Info_Ref
           and then not Is_Subprogram_Import_Export_Subprogram_Parameter
           (The_Subprogram             => The_Subprogram,
            Abstraction                => Previous.Abstraction,
            The_Subprogram_Parameter   => The_Subprogram_Parameter,
            Is_Implicit_Proof_Function => False) loop
            The_Subprogram_Parameter :=
              RawDict.Get_Next_Subprogram_Parameter (The_Subprogram_Parameter => The_Subprogram_Parameter);
         end loop;

         if The_Subprogram_Parameter = RawDict.Null_Subprogram_Parameter_Info_Ref then
            The_Global_Variable :=
              RawDict.Get_Subprogram_First_Global_Variable
              (The_Subprogram => The_Subprogram,
               Abstraction    => Previous.Abstraction);
            while not Stop loop
               if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                  Next := NullIterator;
                  exit;
               end if;
               case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                  when RawDict.Subprogram_Variable_Item =>
                     The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                     if Is_Subprogram_Import_Export_Variable
                       (The_Subprogram => The_Subprogram,
                        Abstraction    => Previous.Abstraction,
                        The_Variable   => The_Variable) then
                        Next :=
                          Iterator'
                          (ImportExportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Variable_Symbol (The_Variable),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when RawDict.Subprogram_Parameter_Item =>
                     The_Subprogram_Parameter :=
                       RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                     if Is_Subprogram_Import_Export_Subprogram_Parameter
                       (The_Subprogram             => The_Subprogram,
                        Abstraction                => Previous.Abstraction,
                        The_Subprogram_Parameter   => The_Subprogram_Parameter,
                        Is_Implicit_Proof_Function => False) then
                        Next :=
                          Iterator'
                          (ImportExportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when others => -- non-exec code
                     Stop := True;
                     SystemErrors.Fatal_Error
                       (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                        Msg     => "in Dictionary.Next_Subprogram_Parameter_Import_Export");
               end case;
               The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
            end loop;
         else
            Next :=
              Iterator'
              (ImportExportIterator,
               Previous.Abstraction,
               RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
               NullSymbol);
         end if;
         return Next;
      end Next_Subprogram_Parameter_Import_Export;

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

      function Next_Global_Variable_Import_Export (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Task_Type            : RawDict.Type_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         Next                     : Iterator := NullIterator;
         Stop                     : Boolean  := False;
      begin
         The_Global_Variable := RawDict.Get_Global_Variable_Info_Ref (Previous.Context);
         case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
            when RawDict.Subprogram_Parameter_Item | RawDict.Subprogram_Variable_Item =>
               The_Subprogram := RawDict.Get_Global_Variable_Subprogram (The_Global_Variable => The_Global_Variable);
               while not Stop loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                     when RawDict.Subprogram_Variable_Item =>
                        The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                        if Is_Subprogram_Import_Export_Variable
                          (The_Subprogram => The_Subprogram,
                           Abstraction    => Previous.Abstraction,
                           The_Variable   => The_Variable) then
                           Next :=
                             Iterator'
                             (ImportExportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Variable_Symbol (The_Variable),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when RawDict.Subprogram_Parameter_Item =>
                        The_Subprogram_Parameter :=
                          RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                        if Is_Subprogram_Import_Export_Subprogram_Parameter
                          (The_Subprogram             => The_Subprogram,
                           Abstraction                => Previous.Abstraction,
                           The_Subprogram_Parameter   => The_Subprogram_Parameter,
                           Is_Implicit_Proof_Function => False) then
                           Next :=
                             Iterator'
                             (ImportExportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when others => -- non-exec code
                        Stop := True;
                        SystemErrors.Fatal_Error
                          (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                           Msg     => "in Dictionary.Next_Global_Variable_Import_Export");
                  end case;
               end loop;
            when RawDict.Task_Type_Variable_Item =>
               The_Task_Type := RawDict.Get_Global_Variable_Task_Type (The_Global_Variable => The_Global_Variable);
               loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                  if Is_Task_Type_Import_Export
                    (The_Task_Type => The_Task_Type,
                     Abstraction   => Previous.Abstraction,
                     The_Variable  => The_Variable) then
                     Next :=
                       Iterator'
                       (ImportExportIterator,
                        Previous.Abstraction,
                        RawDict.Get_Variable_Symbol (The_Variable),
                        RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                     exit;
                  end if;
               end loop;
         end case;
         return Next;
      end Next_Global_Variable_Import_Export;

   begin -- Next_Import_Export
      if Previous.Context = NullSymbol then
         Next := Next_Subprogram_Parameter_Import_Export (Previous => Previous);
      else
         Next := Next_Global_Variable_Import_Export (Previous => Previous);
      end if;
      return Next;
   end Next_Import_Export;

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

   function Next_Export (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Next : Iterator;

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

      function Next_Subprogram_Parameter_Export (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         Next                     : Iterator;
         Stop                     : Boolean := False;
      begin
         The_Subprogram_Parameter := RawDict.Get_Subprogram_Parameter_Info_Ref (CurrentSymbol (Previous));
         The_Subprogram           :=
           RawDict.Get_Subprogram_Parameter_Subprogram (The_Subprogram_Parameter => The_Subprogram_Parameter);

         loop
            The_Subprogram_Parameter :=
              RawDict.Get_Next_Subprogram_Parameter (The_Subprogram_Parameter => The_Subprogram_Parameter);
            if The_Subprogram_Parameter = RawDict.Null_Subprogram_Parameter_Info_Ref then
               Next := NullIterator;
               exit;
            end if;
            if Is_Exported_Subprogram_Subprogram_Parameter
              (The_Subprogram             => The_Subprogram,
               Abstraction                => Previous.Abstraction,
               The_Subprogram_Parameter   => The_Subprogram_Parameter,
               Is_Implicit_Proof_Function => False) then
               Next :=
                 Iterator'
                 (ExportIterator,
                  Previous.Abstraction,
                  RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                  NullSymbol);
               exit;
            end if;
         end loop;

         if Next = NullIterator then
            The_Global_Variable :=
              RawDict.Get_Subprogram_First_Global_Variable
              (The_Subprogram => The_Subprogram,
               Abstraction    => Previous.Abstraction);
            while not Stop and then The_Global_Variable /= RawDict.Null_Global_Variable_Info_Ref loop
               case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                  when RawDict.Subprogram_Variable_Item =>
                     The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                     if Is_Exported_Subprogram_Variable
                       (The_Subprogram => The_Subprogram,
                        Abstraction    => Previous.Abstraction,
                        The_Variable   => The_Variable) then
                        Next :=
                          Iterator'
                          (ExportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Variable_Symbol (The_Variable),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when RawDict.Subprogram_Parameter_Item =>
                     The_Subprogram_Parameter :=
                       RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                     if Is_Exported_Subprogram_Subprogram_Parameter
                       (The_Subprogram             => The_Subprogram,
                        Abstraction                => Previous.Abstraction,
                        The_Subprogram_Parameter   => The_Subprogram_Parameter,
                        Is_Implicit_Proof_Function => False) then
                        Next :=
                          Iterator'
                          (ExportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when others => -- non-exec code
                     Stop := True;
                     SystemErrors.Fatal_Error
                       (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                        Msg     => "in Dictionary.Next_Subprogram_Parameter_Export");
               end case;
               The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
            end loop;
         end if;
         return Next;
      end Next_Subprogram_Parameter_Export;

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

      function Next_Global_Variable_Export (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Task_Type            : RawDict.Type_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         Next                     : Iterator := NullIterator;
         Stop                     : Boolean  := False;
      begin
         The_Global_Variable := RawDict.Get_Global_Variable_Info_Ref (Previous.Context);
         case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
            when RawDict.Subprogram_Parameter_Item | RawDict.Subprogram_Variable_Item =>
               The_Subprogram := RawDict.Get_Global_Variable_Subprogram (The_Global_Variable => The_Global_Variable);
               while not Stop loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                     when RawDict.Subprogram_Variable_Item =>
                        The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                        if Is_Exported_Subprogram_Variable
                          (The_Subprogram => The_Subprogram,
                           Abstraction    => Previous.Abstraction,
                           The_Variable   => The_Variable) then
                           Next :=
                             Iterator'
                             (ExportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Variable_Symbol (The_Variable),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when RawDict.Subprogram_Parameter_Item =>
                        The_Subprogram_Parameter :=
                          RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                        if Is_Exported_Subprogram_Subprogram_Parameter
                          (The_Subprogram             => The_Subprogram,
                           Abstraction                => Previous.Abstraction,
                           The_Subprogram_Parameter   => The_Subprogram_Parameter,
                           Is_Implicit_Proof_Function => False) then
                           Next :=
                             Iterator'
                             (ExportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when others => -- non-exec code
                        Stop := True;
                        SystemErrors.Fatal_Error
                          (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                           Msg     => "in Dictionary.Next_Global_Variable_Export");
                  end case;
               end loop;
            when RawDict.Task_Type_Variable_Item =>
               The_Task_Type := RawDict.Get_Global_Variable_Task_Type (The_Global_Variable => The_Global_Variable);
               loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                  if Is_Exported_Task_Type_Variable
                    (The_Task_Type => The_Task_Type,
                     Abstraction   => Previous.Abstraction,
                     The_Variable  => The_Variable) then
                     Next :=
                       Iterator'
                       (ExportIterator,
                        Previous.Abstraction,
                        RawDict.Get_Variable_Symbol (The_Variable),
                        RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                     exit;
                  end if;
               end loop;
         end case;
         return Next;
      end Next_Global_Variable_Export;

   begin -- Next_Export
      if Previous.Context = NullSymbol then
         Next := Next_Subprogram_Parameter_Export (Previous => Previous);
      else
         Next := Next_Global_Variable_Export (Previous => Previous);
      end if;
      return Next;
   end Next_Export;

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

   function Next_Import (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Next : Iterator;

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

      function Next_Subprogram_Parameter_Import (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         Next                     : Iterator;
         Stop                     : Boolean := False;
      begin
         The_Subprogram_Parameter := RawDict.Get_Subprogram_Parameter_Info_Ref (CurrentSymbol (Previous));
         The_Subprogram           :=
           RawDict.Get_Subprogram_Parameter_Subprogram (The_Subprogram_Parameter => The_Subprogram_Parameter);

         loop
            The_Subprogram_Parameter :=
              RawDict.Get_Next_Subprogram_Parameter (The_Subprogram_Parameter => The_Subprogram_Parameter);
            if The_Subprogram_Parameter = RawDict.Null_Subprogram_Parameter_Info_Ref then
               Next := NullIterator;
               exit;
            end if;
            if Is_Imported_Subprogram_Subprogram_Parameter
              (The_Subprogram             => The_Subprogram,
               Abstraction                => Previous.Abstraction,
               The_Subprogram_Parameter   => The_Subprogram_Parameter,
               Is_Implicit_Proof_Function => False) then
               Next :=
                 Iterator'
                 (ImportIterator,
                  Previous.Abstraction,
                  RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                  NullSymbol);
               exit;
            end if;
         end loop;

         if Next = NullIterator then
            The_Global_Variable :=
              RawDict.Get_Subprogram_First_Global_Variable
              (The_Subprogram => The_Subprogram,
               Abstraction    => Previous.Abstraction);
            while not Stop and then The_Global_Variable /= RawDict.Null_Global_Variable_Info_Ref loop
               case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                  when RawDict.Subprogram_Variable_Item =>
                     The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                     if Is_Imported_Subprogram_Variable
                       (The_Subprogram => The_Subprogram,
                        Abstraction    => Previous.Abstraction,
                        The_Variable   => The_Variable) then
                        Next :=
                          Iterator'
                          (ImportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Variable_Symbol (The_Variable),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when RawDict.Subprogram_Parameter_Item =>
                     The_Subprogram_Parameter :=
                       RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                     if Is_Imported_Subprogram_Subprogram_Parameter
                       (The_Subprogram             => The_Subprogram,
                        Abstraction                => Previous.Abstraction,
                        The_Subprogram_Parameter   => The_Subprogram_Parameter,
                        Is_Implicit_Proof_Function => False) then
                        Next :=
                          Iterator'
                          (ImportIterator,
                           Previous.Abstraction,
                           RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                           RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                        Stop := True;
                     end if;
                  when others => -- non-exec code
                     Stop := True;
                     SystemErrors.Fatal_Error
                       (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                        Msg     => "in Dictionary.Next_Subprogram_Parameter_Import");
               end case;
               The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
            end loop;
         end if;
         return Next;
      end Next_Subprogram_Parameter_Import;

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

      function Next_Global_Variable_Import (Previous : Iterator) return Iterator
      --# global in Dict;
      is
         The_Global_Variable      : RawDict.Global_Variable_Info_Ref;
         The_Subprogram           : RawDict.Subprogram_Info_Ref;
         The_Task_Type            : RawDict.Type_Info_Ref;
         The_Variable             : RawDict.Variable_Info_Ref;
         The_Subprogram_Parameter : RawDict.Subprogram_Parameter_Info_Ref;
         Next                     : Iterator := NullIterator;
         Stop                     : Boolean  := False;
      begin
         The_Global_Variable := RawDict.Get_Global_Variable_Info_Ref (Previous.Context);
         case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
            when RawDict.Subprogram_Parameter_Item | RawDict.Subprogram_Variable_Item =>
               The_Subprogram := RawDict.Get_Global_Variable_Subprogram (The_Global_Variable => The_Global_Variable);
               while not Stop loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  case RawDict.Get_Kind_Of_Global_Variable (The_Global_Variable => The_Global_Variable) is
                     when RawDict.Subprogram_Variable_Item =>
                        The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                        if Is_Imported_Subprogram_Variable
                          (The_Subprogram => The_Subprogram,
                           Abstraction    => Previous.Abstraction,
                           The_Variable   => The_Variable) then
                           Next :=
                             Iterator'
                             (ImportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Variable_Symbol (The_Variable),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when RawDict.Subprogram_Parameter_Item =>
                        The_Subprogram_Parameter :=
                          RawDict.Get_Global_Variable_Parameter (The_Global_Variable => The_Global_Variable);
                        if Is_Imported_Subprogram_Subprogram_Parameter
                          (The_Subprogram             => The_Subprogram,
                           Abstraction                => Previous.Abstraction,
                           The_Subprogram_Parameter   => The_Subprogram_Parameter,
                           Is_Implicit_Proof_Function => False) then
                           Next :=
                             Iterator'
                             (ImportIterator,
                              Previous.Abstraction,
                              RawDict.Get_Subprogram_Parameter_Symbol (The_Subprogram_Parameter),
                              RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                           Stop := True;
                        end if;
                     when others => -- non-exec code
                        Stop := True;
                        SystemErrors.Fatal_Error
                          (Sys_Err => SystemErrors.Invalid_Symbol_Table,
                           Msg     => "in Dictionary.Next_Global_Variable_Import");
                  end case;
               end loop;
            when RawDict.Task_Type_Variable_Item =>
               The_Task_Type := RawDict.Get_Global_Variable_Task_Type (The_Global_Variable => The_Global_Variable);
               loop
                  The_Global_Variable := RawDict.Get_Next_Global_Variable (The_Global_Variable => The_Global_Variable);
                  if The_Global_Variable = RawDict.Null_Global_Variable_Info_Ref then
                     Next := NullIterator;
                     exit;
                  end if;
                  The_Variable := RawDict.Get_Global_Variable_Variable (The_Global_Variable => The_Global_Variable);
                  if Is_Imported_Task_Type_Variable
                    (The_Task_Type => The_Task_Type,
                     Abstraction   => Previous.Abstraction,
                     The_Variable  => The_Variable) then
                     Next :=
                       Iterator'
                       (ImportIterator,
                        Previous.Abstraction,
                        RawDict.Get_Variable_Symbol (The_Variable),
                        RawDict.Get_Global_Variable_Symbol (The_Global_Variable));
                     exit;
                  end if;
               end loop;
         end case;
         return Next;
      end Next_Global_Variable_Import;

   begin -- Next_Import
      if Previous.Context = NullSymbol then
         Next := Next_Subprogram_Parameter_Import (Previous => Previous);
      else
         Next := Next_Global_Variable_Import (Previous => Previous);
      end if;
      return Next;
   end Next_Import;

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

   function Next_Dependency (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Dependency : RawDict.Dependency_Info_Ref;
      Next           : Iterator;
   begin
      The_Dependency := RawDict.Get_Next_Dependency (The_Dependency => RawDict.Get_Dependency_Info_Ref (Previous.Context));
      if The_Dependency = RawDict.Null_Dependency_Info_Ref then
         Next := NullIterator;
      else
         case RawDict.Get_Kind_Of_Dependency (The_Dependency => The_Dependency) is
            when RawDict.Dependency_Parameter_Item =>
               Next :=
                 Iterator'
                 (DependencyIterator,
                  IsAbstract,
                  RawDict.Get_Subprogram_Parameter_Symbol
                    (RawDict.Get_Dependency_Import_Parameter (The_Dependency => The_Dependency)),
                  RawDict.Get_Dependency_Symbol (The_Dependency));
            when RawDict.Dependency_Variable_Item =>
               Next :=
                 Iterator'
                 (DependencyIterator,
                  IsAbstract,
                  RawDict.Get_Variable_Symbol (RawDict.Get_Dependency_Import_Variable (The_Dependency => The_Dependency)),
                  RawDict.Get_Dependency_Symbol (The_Dependency));
         end case;
      end if;
      return Next;
   end Next_Dependency;

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

   function Next_Interrupt_Stream_Mapping (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Mapping : Symbol;
      Next    : Iterator;
   begin
      Mapping := RawDict.GetNextInterruptStreamMapping (Previous.Context);
      if Mapping = NullSymbol then
         Next := NullIterator;
      else
         Next := Iterator'(InterruptStreamMappingIterator, IsAbstract, Mapping, Mapping);
      end if;
      return Next;
   end Next_Interrupt_Stream_Mapping;

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

   function Next_Suspends_List_Item (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      SuspendsListItem : Symbol;
      Next             : Iterator;
   begin
      SuspendsListItem := RawDict.GetNextSuspendsListItem (Previous.Context);
      if SuspendsListItem = NullSymbol then
         Next := NullIterator;
      else
         Next :=
           Iterator'(SuspendsListItemIterator, IsAbstract, RawDict.GetSuspendsListItem (SuspendsListItem), SuspendsListItem);
      end if;
      return Next;
   end Next_Suspends_List_Item;

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

   function Next_Virtual_Element (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Virtual_Element : Symbol;
      Next            : Iterator;
   begin
      Virtual_Element := RawDict.GetNextVirtualElement (Previous.Context);
      if Virtual_Element = NullSymbol then
         Next := NullIterator;
      else
         Next :=
           Iterator'
           (VirtualElementIterator,
            IsAbstract,
            RawDict.Get_Variable_Symbol (RawDict.GetVirtualElementVariable (Virtual_Element)),
            Virtual_Element);
      end if;
      return Next;
   end Next_Virtual_Element;

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

   function Next_Owned_Package (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Previous_Package, Current_Package, Descendent : RawDict.Package_Info_Ref;
      Next                                          : Iterator;
   begin
      Previous_Package := RawDict.Get_Package_Info_Ref (CurrentSymbol (Previous));
      Current_Package  := RawDict.Get_Package_Next_Sibling (The_Package => Previous_Package);

      if Current_Package /= RawDict.Null_Package_Info_Ref then
         loop
            Descendent := RawDict.Get_Package_First_Public_Child (The_Package => Current_Package);
            exit when Descendent = RawDict.Null_Package_Info_Ref;
            Current_Package := Descendent;
         end loop;
      elsif not RawDict.Get_Package_Is_Private (The_Package => Previous_Package) then
         Current_Package := RawDict.Get_Package_Parent (The_Package => Previous_Package);
      end if;

      if Current_Package = RawDict.Null_Package_Info_Ref then
         Next := NullIterator;
      else
         Next := Iterator'(OwnedPackageIterator, IsAbstract, RawDict.Get_Package_Symbol (Current_Package), Previous.Context);
      end if;
      return Next;
   end Next_Owned_Package;

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

   function Next_Embedded_Package (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Declaration : RawDict.Declaration_Info_Ref;
      Item            : Symbol;
      Next            : Iterator := NullIterator;
   begin
      The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => RawDict.Get_Declaration_Info_Ref (Previous.Context));
      while The_Declaration /= RawDict.Null_Declaration_Info_Ref loop
         Item := RawDict.Get_Declaration_Item (The_Declaration => The_Declaration);
         if RawDict.GetSymbolDiscriminant (Item) = Package_Symbol
           and then The_Declaration /= RawDict.Get_Package_Body (The_Package => RawDict.Get_Package_Info_Ref (Item => Item)) then
            Next            :=
              Iterator'
              (EmbeddedPackageIterator,
               IsAbstract,
               Item,
               RawDict.Get_Declaration_Symbol (The_Declaration => The_Declaration));
            The_Declaration := RawDict.Null_Declaration_Info_Ref;
         else
            The_Declaration := RawDict.Get_Next_Declaration (The_Declaration => The_Declaration);
         end if;
      end loop;
      return Next;
   end Next_Embedded_Package;

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

   function Next_Own_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Own_Variable : RawDict.Own_Variable_Info_Ref;
      Next         : Iterator;
   begin
      Own_Variable := RawDict.Get_Next_Own_Variable (The_Own_Variable => RawDict.Get_Own_Variable_Info_Ref (Previous.Current));
      if Own_Variable = RawDict.Null_Own_Variable_Info_Ref then
         Next := NullIterator;
      else
         Next := Iterator'(OwnVariableIterator, IsAbstract, RawDict.Get_Own_Variable_Symbol (Own_Variable), NullSymbol);
      end if;
      return Next;
   end Next_Own_Variable;

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

   function Next_Initialized_Own_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Own_Variable : RawDict.Own_Variable_Info_Ref;
      Next         : Iterator;
   begin
      Own_Variable := RawDict.Get_Next_Own_Variable (The_Own_Variable => RawDict.Get_Own_Variable_Info_Ref (Previous.Current));
      loop
         if Own_Variable = RawDict.Null_Own_Variable_Info_Ref then
            Next := NullIterator;
            exit;
         end if;

         if RawDict.Get_Own_Variable_Initialized (The_Own_Variable => Own_Variable) then
            Next :=
              Iterator'(InitializedOwnVariableIterator, IsAbstract, RawDict.Get_Own_Variable_Symbol (Own_Variable), NullSymbol);
            exit;
         end if;
         Own_Variable := RawDict.Get_Next_Own_Variable (The_Own_Variable => Own_Variable);
      end loop;
      return Next;
   end Next_Initialized_Own_Variable;

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

   function Next_Abstract_Own_Variable (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Own_Variable : RawDict.Own_Variable_Info_Ref;
      Next         : Iterator;
   begin
      Own_Variable := RawDict.Get_Next_Own_Variable (The_Own_Variable => RawDict.Get_Own_Variable_Info_Ref (Previous.Current));
      loop
         if Own_Variable = RawDict.Null_Own_Variable_Info_Ref then
            Next := NullIterator;
            exit;
         end if;

         if RawDict.Get_Own_Variable_Constituents (The_Own_Variable => Own_Variable) /= RawDict.Null_Constituent_Info_Ref then
            Next :=
              Iterator'(AbstractOwnVariableIterator, IsAbstract, RawDict.Get_Own_Variable_Symbol (Own_Variable), NullSymbol);
            exit;
         end if;
         Own_Variable := RawDict.Get_Next_Own_Variable (The_Own_Variable => Own_Variable);
      end loop;
      return Next;
   end Next_Abstract_Own_Variable;

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

   function Next_Constituent (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Constituent : RawDict.Constituent_Info_Ref;
      Next            : Iterator := NullIterator;
   begin
      The_Constituent := RawDict.Get_Next_Constituent (The_Constituent => RawDict.Get_Constituent_Info_Ref (Previous.Current));
      if The_Constituent /= RawDict.Null_Constituent_Info_Ref then
         Next := Iterator'(ConstituentIterator, IsAbstract, RawDict.Get_Constituent_Symbol (The_Constituent), NullSymbol);
      end if;
      return Next;
   end Next_Constituent;

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

   function Next_Known_Discriminant (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Discriminant : Symbol;
      Next         : Iterator;
   begin
      Discriminant := RawDict.GetNextDiscriminant (Previous.Current);
      if Discriminant = NullSymbol then
         Next := NullIterator;
      else
         Next := Iterator'(KnownDiscriminantIterator, IsAbstract, Discriminant, NullSymbol);
      end if;
      return Next;
   end Next_Known_Discriminant;

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

   function Next_Discriminant_Constraint (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Discriminant : Symbol;
      Next         : Iterator;
   begin
      Discriminant := RawDict.GetNextDiscriminantConstraint (Previous.Current);
      if Discriminant = NullSymbol then
         Next := NullIterator;
      else
         Next := Iterator'(DiscriminantConstraintIterator, IsAbstract, Discriminant, NullSymbol);
      end if;
      return Next;
   end Next_Discriminant_Constraint;

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

   function Next_Generic_Formal_Parameter (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      The_Generic_Parameter : RawDict.Generic_Parameter_Info_Ref;
      Result                : Iterator;
   begin
      The_Generic_Parameter :=
        RawDict.Get_Next_Generic_Parameter (The_Generic_Parameter => RawDict.Get_Generic_Parameter_Info_Ref (Previous.Current));
      if The_Generic_Parameter = RawDict.Null_Generic_Parameter_Info_Ref then
         Result := NullIterator;
      else
         Result :=
           Iterator'
           (GenericFormalParameterIterator,
            IsAbstract,
            RawDict.Get_Generic_Parameter_Symbol (The_Generic_Parameter),
            NullSymbol);
      end if;
      return Result;
   end Next_Generic_Formal_Parameter;

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

   function Next_Loop_On_Entry_Var (Previous : Iterator) return Iterator
   --# global in Dict;
   is
      Next   : Symbol;
      Result : Iterator;
   begin
      Next := RawDict.GetLoopEntryVariableNext (Previous.Current);
      if Next = NullSymbol then
         Result := NullIterator;
      else
         Result := Iterator'(LoopOnEntryVarIterator, IsAbstract, Next, NullSymbol);
      end if;
      return Result;
   end Next_Loop_On_Entry_Var;

begin -- NextSymbol
   case Previous.Discriminant is
      when NullSymIterator | DeclarativeItemIterator =>
         Next := Next_Declarative_Item (Previous => Previous);
      when DeferredConstantIterator =>
         Next := Next_Deferred_Constant (Previous => Previous);
      when ArrayIndexIterator =>
         Next := Next_Array_Index (Previous => Previous);
      when LoopIterator =>
         Next := Next_Loop (Previous => Previous);
      when UndeclaredTypeIterator =>
         Next := Next_Undeclared_Type (Previous => Previous);
      when PrivateTypeIterator =>
         Next := Next_Private_Type (Previous => Previous);
      when EnumerationLiteralIterator =>
         Next := Next_Enumeration_Literal (Previous => Previous);
      when RecordComponentIterator =>
         Next := Next_Record_Component (Previous => Previous);
      when ExtendedRecordComponentIterator =>
         Next := Next_Extended_Record_Component (Previous => Previous);
      when LibraryUnitIterator =>
         Next := Next_Library_Unit (Previous => Previous);
      when WithedPackageIterator =>
         Next := Next_Withed_Package (Previous => Previous);
      when InheritedPackageIterator =>
         Next := Next_Inherited_Package (Previous => Previous);
      when VisibleSubprogramIterator | PrivateSubprogramIterator =>
         Next := Next_Visible_Or_Private_Subprogram (Previous => Previous);
      when TaskTypeIterator =>
         Next := Next_Task_Type (Previous => Previous);
      when OwnTaskIterator =>
         Next := Next_Own_Task (Previous => Previous);
      when ProtectedTypeIterator =>
         Next := Next_Protected_Type (Previous => Previous);
      when SubprogramParameterIterator | ImplicitProofFunctionGlobalIterator | ImplicitProofFunctionParameterIterator =>
         Next := Next_Subprogram_Parameter (Previous => Previous);
      when KnownDiscriminantIterator =>
         Next := Next_Known_Discriminant (Previous => Previous);
      when DiscriminantConstraintIterator =>
         Next := Next_Discriminant_Constraint (Previous => Previous);
      when GlobalVariableIterator =>
         Next := Next_Global_Variable (Previous => Previous);
      when LocalVariableIterator =>
         Next := Next_Local_Variable (Previous => Previous);
      when ProtectedElementIterator =>
         Next := Next_Protected_Element (Previous => Previous);
      when InitializedVariableIterator =>
         Next := Next_Initialized_Variable (Previous => Previous);
      when ImportExportIterator =>
         Next := Next_Import_Export (Previous => Previous);
      when ExportIterator =>
         Next := Next_Export (Previous => Previous);
      when ImportIterator =>
         Next := Next_Import (Previous => Previous);
      when DependencyIterator =>
         Next := Next_Dependency (Previous => Previous);
      when InterruptStreamMappingIterator =>
         Next := Next_Interrupt_Stream_Mapping (Previous => Previous);
      when SuspendsListItemIterator =>
         Next := Next_Suspends_List_Item (Previous => Previous);
      when VirtualElementIterator =>
         Next := Next_Virtual_Element (Previous => Previous);
      when OwnedPackageIterator =>
         Next := Next_Owned_Package (Previous => Previous);
      when EmbeddedPackageIterator =>
         Next := Next_Embedded_Package (Previous => Previous);
      when OwnVariableIterator =>
         Next := Next_Own_Variable (Previous => Previous);
      when InitializedOwnVariableIterator =>
         Next := Next_Initialized_Own_Variable (Previous => Previous);
      when AbstractOwnVariableIterator =>
         Next := Next_Abstract_Own_Variable (Previous => Previous);
      when ConstituentIterator =>
         Next := Next_Constituent (Previous => Previous);
      when GenericFormalParameterIterator =>
         Next := Next_Generic_Formal_Parameter (Previous => Previous);
      when LoopOnEntryVarIterator =>
         Next := Next_Loop_On_Entry_Var (Previous => Previous);
   end case;
   return Next;
end NextSymbol;
