-------------------------------------------------------------------------------
-- (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 (Sem.Dependency_Relation)
procedure Check_Derives_Consistency
  (Subprog_Sym : in     Dictionary.Symbol;
   Position    : in     LexTokenManager.Token_Position;
   The_Heap    : in out Heap.HeapRecord)
is
   R, RT                      : RelationAlgebra.Relation;
   R_Dom, RT_Dom, A_Unchanged : SeqAlgebra.Seq;

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

   function Sym_To_Nat (Sym : in Dictionary.Symbol) return Natural is
   begin
      return Natural (Dictionary.SymbolRef (Sym));
   end Sym_To_Nat;

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

   function Mem_To_Sym (Nat      : SeqAlgebra.MemberOfSeq;
                        The_Heap : Heap.HeapRecord) return Dictionary.Symbol is
   begin
      return Dictionary.ConvertSymbolRef
        (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                M        => Nat)));
   end Mem_To_Sym;

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

   procedure Build_RT
     (Subprog_Sym : in     Dictionary.Symbol;
      The_Heap    : in out Heap.HeapRecord;
      RT          :    out RelationAlgebra.Relation;
      RT_Dom      :    out SeqAlgebra.Seq;
      A_Unchanged :    out SeqAlgebra.Seq)
   --# global in     Dictionary.Dict;
   --#        in out Statistics.TableUsage;
   --# derives A_Unchanged,
   --#         RT_Dom,
   --#         The_Heap              from Dictionary.Dict,
   --#                                    Subprog_Sym,
   --#                                    The_Heap &
   --#         RT                    from The_Heap &
   --#         Statistics.TableUsage from *,
   --#                                    Dictionary.Dict,
   --#                                    Subprog_Sym,
   --#                                    The_Heap;
   is

      -- GAA duplicated code from SEM-WF_GLOBAL_DEFINITION.ADB
      function Valid_Refinement (Constituent, Subprogram : Dictionary.Symbol) return Boolean
      --# global in Dictionary.Dict;
      is
         Owner, Region, Enclosing_Region : Dictionary.Symbol;
         Result                          : Boolean := False;
      begin
         if Dictionary.IsConstituent (Constituent) then
            -- We regard Constituent as a Valid_Refinement if:
            --   It is a refinement constituent of Subject AND
            --      (Subject is owned by the region in which the Subprogram is declared OR
            --       Subject is owned by the region in which the protected type in which the
            --          Subprogram is declared)
            Owner  := Dictionary.GetOwner (Dictionary.GetSubject (Constituent));
            Region := Dictionary.GetRegion (Dictionary.GetScope (Subprogram));
            Result := Owner = Region;
            if not Result and then Dictionary.IsProtectedType (Region) then
               Enclosing_Region := Dictionary.GetRegion (Dictionary.GetScope (Region));
               Result           := Owner = Enclosing_Region;
            end if;
         end if;
         return Result;
      end Valid_Refinement;

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

      procedure Step_One
        (RT          : in     RelationAlgebra.Relation;
         Subprog_Sym : in     Dictionary.Symbol;
         The_Heap    : in out Heap.HeapRecord;
         RT_Dom      :    out SeqAlgebra.Seq;
         A_Unchanged :    out SeqAlgebra.Seq)
      --# global in     Dictionary.Dict;
      --#        in out Statistics.TableUsage;
      --# derives A_Unchanged           from Dictionary.Dict,
      --#                                    Subprog_Sym,
      --#                                    The_Heap &
      --#         RT_Dom,
      --#         The_Heap              from Dictionary.Dict,
      --#                                    RT,
      --#                                    Subprog_Sym,
      --#                                    The_Heap &
      --#         Statistics.TableUsage from *,
      --#                                    Dictionary.Dict,
      --#                                    RT,
      --#                                    Subprog_Sym,
      --#                                    The_Heap;
      is
         CA_Exp, C_Exp, Unchanged, Empty_Seq : SeqAlgebra.Seq;

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

         procedure Build_CA_Exp
           (CA_Exp      :    out SeqAlgebra.Seq;
            Subprog_Sym : in     Dictionary.Symbol;
            The_Heap    : in out Heap.HeapRecord)
         --# global in     Dictionary.Dict;
         --#        in out Statistics.TableUsage;
         --# derives CA_Exp                from The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap              from *,
         --#                                    Dictionary.Dict,
         --#                                    Subprog_Sym,
         --#                                    The_Heap;
         is
            Concrete_Export, Constituent_Sym   : Dictionary.Symbol;
            Concrete_Export_It, Constituent_It : Dictionary.Iterator;
         begin
            SeqAlgebra.CreateSeq (The_Heap, CA_Exp);
            Concrete_Export_It := Dictionary.FirstExport (Dictionary.IsRefined, Subprog_Sym);
            while not Dictionary.IsNullIterator (Concrete_Export_It) loop
               Concrete_Export := Dictionary.CurrentSymbol (Concrete_Export_It);
               if Valid_Refinement (Constituent => Concrete_Export,
                                    Subprogram  => Subprog_Sym) then
                  Constituent_It := Dictionary.FirstConstituent (Dictionary.GetSubject (Concrete_Export));
                  while not Dictionary.IsNullIterator (Constituent_It) loop
                     Constituent_Sym := Dictionary.CurrentSymbol (Constituent_It);
                     -- Previously we only add constituents to CA_Exp if they are unmoded; this has been shown to
                     -- be incorrect (see SEPR 1844), so now we add all constituents
                     SeqAlgebra.AddMember (The_Heap, CA_Exp, Sym_To_Nat (Sym => Constituent_Sym));

                     Constituent_It := Dictionary.NextSymbol (Constituent_It);
                  end loop;
               end if;
               Concrete_Export_It := Dictionary.NextSymbol (Concrete_Export_It);
            end loop;
         end Build_CA_Exp;

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

         procedure Build_C_Exp
           (C_Exp       :    out SeqAlgebra.Seq;
            Subprog_Sym : in     Dictionary.Symbol;
            The_Heap    : in out Heap.HeapRecord)
         --# global in     Dictionary.Dict;
         --#        in out Statistics.TableUsage;
         --# derives C_Exp                 from The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap              from *,
         --#                                    Dictionary.Dict,
         --#                                    Subprog_Sym,
         --#                                    The_Heap;
         is
            Concrete_Export_It : Dictionary.Iterator;
         begin
            SeqAlgebra.CreateSeq (The_Heap, C_Exp);
            Concrete_Export_It := Dictionary.FirstExport (Dictionary.IsRefined, Subprog_Sym);
            while not Dictionary.IsNullIterator (Concrete_Export_It) loop
               SeqAlgebra.AddMember (The_Heap, C_Exp, Sym_To_Nat (Sym => Dictionary.CurrentSymbol (Concrete_Export_It)));
               Concrete_Export_It := Dictionary.NextSymbol (Concrete_Export_It);
            end loop;
         end Build_C_Exp;

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

         procedure Abstract_Unchanged (U        : in     SeqAlgebra.Seq;
                                       AU       :    out SeqAlgebra.Seq;
                                       The_Heap : in out Heap.HeapRecord)
         --# global in     Dictionary.Dict;
         --#        in out Statistics.TableUsage;
         --# derives AU                    from The_Heap &
         --#         Statistics.TableUsage,
         --#         The_Heap              from *,
         --#                                    Dictionary.Dict,
         --#                                    The_Heap,
         --#                                    U;
         is
            Mem : SeqAlgebra.MemberOfSeq;
         begin
            SeqAlgebra.CreateSeq (The_Heap, AU);
            Mem := SeqAlgebra.FirstMember (The_Heap, U);
            while not SeqAlgebra.IsNullMember (Mem) loop
               SeqAlgebra.AddMember
                 (The_Heap,
                  AU,
                  Sym_To_Nat (Sym => Dictionary.GetSubject (Mem_To_Sym (Nat      => Mem,
                                                                        The_Heap => The_Heap))));
               Mem := SeqAlgebra.NextMember (The_Heap, Mem);
            end loop;
         end Abstract_Unchanged;

      begin -- Step_One

         -- set of all constituents of subject of any exported constituent
         Build_CA_Exp (CA_Exp      => CA_Exp,
                       Subprog_Sym => Subprog_Sym,
                       The_Heap    => The_Heap);
         -- set of actual exported constituents
         Build_C_Exp (C_Exp       => C_Exp,
                      Subprog_Sym => Subprog_Sym,
                      The_Heap    => The_Heap);
         -- unwritten constituents
         SeqAlgebra.Complement (The_Heap, CA_Exp, C_Exp, Unchanged);
         -- abstract subjects of unwritten constituents
         Abstract_Unchanged (U        => Unchanged,
                             AU       => A_Unchanged,
                             The_Heap => The_Heap);
         -- depend on themselves
         RelationAlgebra.AddIdentity (The_Heap, RT, A_Unchanged);
         SeqAlgebra.CreateSeq (The_Heap, Empty_Seq);
         SeqAlgebra.Union (The_Heap, A_Unchanged, Empty_Seq, RT_Dom);
         SeqAlgebra.DisposeOfSeq (The_Heap, Empty_Seq);
         SeqAlgebra.DisposeOfSeq (The_Heap, CA_Exp);
         SeqAlgebra.DisposeOfSeq (The_Heap, C_Exp);
         SeqAlgebra.DisposeOfSeq (The_Heap, Unchanged);
      end Step_One;

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

      procedure Steps_Two_And_Three
        (RT          : in     RelationAlgebra.Relation;
         RT_Dom      : in     SeqAlgebra.Seq;
         Subprog_Sym : in     Dictionary.Symbol;
         The_Heap    : in out Heap.HeapRecord)
      --# global in     Dictionary.Dict;
      --#        in out Statistics.TableUsage;
      --# derives Statistics.TableUsage,
      --#         The_Heap              from *,
      --#                                    Dictionary.Dict,
      --#                                    RT,
      --#                                    RT_Dom,
      --#                                    Subprog_Sym,
      --#                                    The_Heap;
      is
         Export_Var, Import_Var : Dictionary.Symbol;
         Export_Num, Import_Num : Natural;
         Export_It, Import_It   : Dictionary.Iterator;
      begin
         Export_It := Dictionary.FirstExport (Dictionary.IsRefined, Subprog_Sym);
         while not Dictionary.IsNullIterator (Export_It) loop
            Export_Var := Dictionary.CurrentSymbol (Export_It);
            if Valid_Refinement (Constituent => Export_Var,
                                 Subprogram  => Subprog_Sym) then
               Export_Num := Sym_To_Nat (Sym => Dictionary.GetSubject (Export_Var));
            else
               Export_Num := Sym_To_Nat (Sym => Export_Var);
            end if;
            SeqAlgebra.AddMember (The_Heap, RT_Dom, Export_Num);
            -- if it's mode out stream add Export_Num, Export_Num to RT
            if Dictionary.GetOwnVariableOrConstituentMode (Export_Var) = Dictionary.OutMode then
               RelationAlgebra.InsertPair (The_Heap, RT, Export_Num, Export_Num);
            end if;
            Import_It := Dictionary.FirstDependency (Dictionary.IsRefined, Subprog_Sym, Export_Var);
            while not Dictionary.IsNullIterator (Import_It) loop
               Import_Var := Dictionary.CurrentSymbol (Import_It);
               if Valid_Refinement (Constituent => Import_Var,
                                    Subprogram  => Subprog_Sym) then
                  Import_Num := Sym_To_Nat (Sym => Dictionary.GetSubject (Import_Var));
               else
                  Import_Num := Sym_To_Nat (Sym => Import_Var);
               end if;
               RelationAlgebra.InsertPair (The_Heap, RT, Export_Num, Import_Num);
               -- if it's a mode in stream then add Import_Num, Import_Num to RT
               -- and add Import_Num to RT_Dom
               if Dictionary.GetOwnVariableOrConstituentMode (Import_Var) = Dictionary.InMode then
                  RelationAlgebra.InsertPair (The_Heap, RT, Import_Num, Import_Num);
                  SeqAlgebra.AddMember (The_Heap, RT_Dom, Import_Num);
               end if;
               Import_It := Dictionary.NextSymbol (Import_It);
            end loop;
            Export_It := Dictionary.NextSymbol (Export_It);
         end loop;
      end Steps_Two_And_Three;

   begin -- Build_RT
      RelationAlgebra.CreateRelation (The_Heap, RT);
      Step_One (RT          => RT,
                Subprog_Sym => Subprog_Sym,
                The_Heap    => The_Heap,
                RT_Dom      => RT_Dom,
                A_Unchanged => A_Unchanged);
      Steps_Two_And_Three (RT          => RT,
                           RT_Dom      => RT_Dom,
                           Subprog_Sym => Subprog_Sym,
                           The_Heap    => The_Heap);
   end Build_RT;

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

   procedure Build_R
     (Subprog_Sym : in     Dictionary.Symbol;
      The_Heap    : in out Heap.HeapRecord;
      R           :    out RelationAlgebra.Relation;
      R_Dom       :    out SeqAlgebra.Seq)
   --# global in     Dictionary.Dict;
   --#        in out Statistics.TableUsage;
   --# derives R,
   --#         R_Dom                 from The_Heap &
   --#         Statistics.TableUsage,
   --#         The_Heap              from *,
   --#                                    Dictionary.Dict,
   --#                                    Subprog_Sym,
   --#                                    The_Heap;
   is
      LR                     : RelationAlgebra.Relation;
      Export_Var, Import_Var : Dictionary.Symbol;
      Export_Num, Import_Num : Natural;
      Export_It, Import_It   : Dictionary.Iterator;
   begin
      RelationAlgebra.CreateRelation (The_Heap, LR);
      SeqAlgebra.CreateSeq (The_Heap, R_Dom);
      Export_It := Dictionary.FirstExport (Dictionary.IsAbstract, Subprog_Sym);
      while not Dictionary.IsNullIterator (Export_It) loop
         Export_Var := Dictionary.CurrentSymbol (Export_It);
         Export_Num := Sym_To_Nat (Sym => Export_Var);
         SeqAlgebra.AddMember (The_Heap, R_Dom, Export_Num);
         -- if it's mode out stream add Export_Num, Export_Num to LR
         if Dictionary.GetOwnVariableOrConstituentMode (Export_Var) = Dictionary.OutMode then
            RelationAlgebra.InsertPair (The_Heap, LR, Export_Num, Export_Num);
         end if;
         Import_It := Dictionary.FirstDependency (Dictionary.IsAbstract, Subprog_Sym, Export_Var);
         while not Dictionary.IsNullIterator (Import_It) loop
            Import_Var := Dictionary.CurrentSymbol (Import_It);
            Import_Num := Sym_To_Nat (Sym => Import_Var);
            RelationAlgebra.InsertPair (The_Heap, LR, Export_Num, Import_Num);
            -- if it's a mode in stream then add Import_It, Import_It to LR
            -- and add Import_It to R_Dom
            if Dictionary.GetOwnVariableOrConstituentMode (Import_Var) = Dictionary.InMode then
               RelationAlgebra.InsertPair (The_Heap, LR, Import_Num, Import_Num);
               SeqAlgebra.AddMember (The_Heap, R_Dom, Import_Num);
            end if;
            Import_It := Dictionary.NextSymbol (Import_It);
         end loop;
         Export_It := Dictionary.NextSymbol (Export_It);
      end loop;
      R := LR;
   end Build_R;

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

   procedure Type_One_Errors
     (R           : in     RelationAlgebra.Relation;
      R_Dom       : in     SeqAlgebra.Seq;
      RT          : in     RelationAlgebra.Relation;
      RT_Dom      : in     SeqAlgebra.Seq;
      A_Unchanged : in     SeqAlgebra.Seq;
      Subprog_Sym : in     Dictionary.Symbol;
      The_Heap    : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in     Position;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from A_Unchanged,
   --#                                         CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Position,
   --#                                         R,
   --#                                         RT,
   --#                                         RT_Dom,
   --#                                         R_Dom,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym,
   --#                                         The_Heap &
   --#         Statistics.TableUsage,
   --#         The_Heap                   from *,
   --#                                         R,
   --#                                         RT,
   --#                                         RT_Dom,
   --#                                         R_Dom,
   --#                                         The_Heap;
   is
      R_Row, RT_Row, Diff : SeqAlgebra.Seq;
      R_Exp, Err_Imp      : SeqAlgebra.MemberOfSeq;
      Subprog_Scope       : Dictionary.Scopes;
   begin
      Subprog_Scope := Dictionary.GetScope (Subprog_Sym);
      R_Exp         := SeqAlgebra.FirstMember (The_Heap, R_Dom);
      loop
         exit when SeqAlgebra.IsNullMember (R_Exp);
         if not SeqAlgebra.IsMember (The_Heap, RT_Dom, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                   M        => R_Exp)) then
            -- special case: we do not want to issue Error 1 for an abstract own
            -- variable of mode in since a message saying we have failed to update
            -- such a variable is bound to misleading (the updating is only implicit anyway)
            if Dictionary.GetOwnVariableOrConstituentMode (Mem_To_Sym (Nat      => R_Exp,
                                                                       The_Heap => The_Heap)) /=
              Dictionary.InMode then
               ErrorHandler.Dep_Semantic_Error_Sym
                 (Err_Num  => 1,
                  Position => Position,
                  Sym1     => Mem_To_Sym (Nat      => R_Exp,
                                          The_Heap => The_Heap),
                  Sym2     => Dictionary.NullSymbol,
                  Scope    => Subprog_Scope);
            end if;
         else
            RelationAlgebra.RowExtraction (The_Heap, R, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                    M        => R_Exp), R_Row);
            RelationAlgebra.RowExtraction (The_Heap, RT, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                     M        => R_Exp), RT_Row);
            SeqAlgebra.Complement (The_Heap, RT_Row, R_Row, Diff);
            Err_Imp := SeqAlgebra.FirstMember (The_Heap, Diff);
            loop
               exit when SeqAlgebra.IsNullMember (Err_Imp);
               if Mem_To_Sym (Nat      => Err_Imp,
                              The_Heap => The_Heap) = Mem_To_Sym (Nat      => R_Exp,
                                                                  The_Heap => The_Heap)
                 and then SeqAlgebra.IsMember
                 (The_Heap,
                  A_Unchanged,
                  SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                              M        => Err_Imp)) then
                  ErrorHandler.Dep_Semantic_Error_Sym
                    (Err_Num  => 5,
                     Position => Position,
                     Sym1     => Mem_To_Sym (Nat      => R_Exp,
                                             The_Heap => The_Heap),
                     Sym2     => Dictionary.NullSymbol,
                     Scope    => Subprog_Scope);
               else
                  ErrorHandler.Dep_Semantic_Error_Sym
                    (Err_Num  => 4,
                     Position => Position,
                     Sym1     => Mem_To_Sym (Nat      => R_Exp,
                                             The_Heap => The_Heap),
                     Sym2     => Mem_To_Sym (Nat      => Err_Imp,
                                             The_Heap => The_Heap),
                     Scope    => Subprog_Scope);
               end if;
               Err_Imp := SeqAlgebra.NextMember (The_Heap, Err_Imp);
            end loop;
         end if;
         R_Exp := SeqAlgebra.NextMember (The_Heap, R_Exp);
      end loop;
   end Type_One_Errors;

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

   procedure Type_Two_Errors
     (R           : in     RelationAlgebra.Relation;
      R_Dom       : in     SeqAlgebra.Seq;
      RT          : in     RelationAlgebra.Relation;
      RT_Dom      : in     SeqAlgebra.Seq;
      Subprog_Sym : in     Dictionary.Symbol;
      The_Heap    : in out Heap.HeapRecord)
   --# global in     CommandLineData.Content;
   --#        in     Dictionary.Dict;
   --#        in     LexTokenManager.State;
   --#        in     Position;
   --#        in out ErrorHandler.Error_Context;
   --#        in out SPARK_IO.File_Sys;
   --#        in out Statistics.TableUsage;
   --# derives ErrorHandler.Error_Context,
   --#         SPARK_IO.File_Sys          from CommandLineData.Content,
   --#                                         Dictionary.Dict,
   --#                                         ErrorHandler.Error_Context,
   --#                                         LexTokenManager.State,
   --#                                         Position,
   --#                                         R,
   --#                                         RT,
   --#                                         RT_Dom,
   --#                                         R_Dom,
   --#                                         SPARK_IO.File_Sys,
   --#                                         Subprog_Sym,
   --#                                         The_Heap &
   --#         Statistics.TableUsage,
   --#         The_Heap                   from *,
   --#                                         Dictionary.Dict,
   --#                                         R,
   --#                                         RT,
   --#                                         RT_Dom,
   --#                                         R_Dom,
   --#                                         The_Heap;
   is
      R_Row, RT_Row, Diff : SeqAlgebra.Seq;
      RT_Exp, Err_Imp     : SeqAlgebra.MemberOfSeq;
      Subprog_Scope       : Dictionary.Scopes;
   begin
      Subprog_Scope := Dictionary.GetScope (Subprog_Sym);
      RT_Exp        := SeqAlgebra.FirstMember (The_Heap, RT_Dom);
      loop
         exit when SeqAlgebra.IsNullMember (RT_Exp);
         if not SeqAlgebra.IsMember (The_Heap, R_Dom, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                  M        => RT_Exp))
           and then not Dictionary.Is_Null_Variable (Mem_To_Sym (Nat      => RT_Exp,
                                                                 The_Heap => The_Heap)) then
            -- don't report refinement errors on Null
            ErrorHandler.Dep_Semantic_Error_Sym
              (Err_Num  => 2,
               Position => Position,
               Sym1     => Mem_To_Sym (Nat      => RT_Exp,
                                       The_Heap => The_Heap),
               Sym2     => Dictionary.NullSymbol,
               Scope    => Subprog_Scope);
         else
            RelationAlgebra.RowExtraction (The_Heap, R, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                    M        => RT_Exp), R_Row);
            RelationAlgebra.RowExtraction (The_Heap, RT, SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                     M        => RT_Exp), RT_Row);
            SeqAlgebra.Complement (The_Heap, R_Row, RT_Row, Diff);
            Err_Imp := SeqAlgebra.FirstMember (The_Heap, Diff);
            loop
               exit when SeqAlgebra.IsNullMember (Err_Imp);

               -- guard to avoid spurious refinement errors in DFA mode
               if CommandLineData.Content.Flow_Option /= CommandLineData.Data_Flow
                 or else Mem_To_Sym (Nat      => RT_Exp,
                                     The_Heap => The_Heap) = Mem_To_Sym (Nat      => Err_Imp,
                                                                         The_Heap => The_Heap) then
                  ErrorHandler.Dep_Semantic_Error_Sym
                    (Err_Num  => 3,
                     Position => Position,
                     Sym1     => Mem_To_Sym (Nat      => RT_Exp,
                                             The_Heap => The_Heap),
                     Sym2     => Mem_To_Sym (Nat      => Err_Imp,
                                             The_Heap => The_Heap),
                     Scope    => Subprog_Scope);
               end if;
               Err_Imp := SeqAlgebra.NextMember (The_Heap, Err_Imp);
            end loop;
         end if;
         RT_Exp := SeqAlgebra.NextMember (The_Heap, RT_Exp);
      end loop;
   end Type_Two_Errors;

begin -- Check_Derives_Consistency
   Build_RT (Subprog_Sym => Subprog_Sym,
             The_Heap    => The_Heap,
             RT          => RT,
             RT_Dom      => RT_Dom,
             A_Unchanged => A_Unchanged);
   Build_R (Subprog_Sym => Subprog_Sym,
            The_Heap    => The_Heap,
            R           => R,
            R_Dom       => R_Dom);
   Type_One_Errors
     (R           => R,
      R_Dom       => R_Dom,
      RT          => RT,
      RT_Dom      => RT_Dom,
      A_Unchanged => A_Unchanged,
      Subprog_Sym => Subprog_Sym,
      The_Heap    => The_Heap);
   Type_Two_Errors (R           => R,
                    R_Dom       => R_Dom,
                    RT          => RT,
                    RT_Dom      => RT_Dom,
                    Subprog_Sym => Subprog_Sym,
                    The_Heap    => The_Heap);
   RelationAlgebra.DisposeOfRelation (The_Heap, RT);
   RelationAlgebra.DisposeOfRelation (The_Heap, R);
   SeqAlgebra.DisposeOfSeq (The_Heap, RT_Dom);
   SeqAlgebra.DisposeOfSeq (The_Heap, R_Dom);
   SeqAlgebra.DisposeOfSeq (The_Heap, A_Unchanged);
   Heap.ReportUsage (The_Heap);
end Check_Derives_Consistency;
