-------------------------------------------------------------------------------
-- (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 Create_Full_Dependency
  (Node_Pos                 : in LexTokenManager.Token_Position;
   Subprog_Sym              : in Dictionary.Symbol;
   Abstraction              : in Dictionary.Abstractions;
   Import_List, Export_List : in SeqAlgebra.Seq;
   The_Heap                 : in Heap.HeapRecord)
is

   First_Valid_Export : Dictionary.Symbol;
   Member             : SeqAlgebra.MemberOfSeq;
   Import             : Dictionary.Symbol;

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

   function Get_First_Valid_Export (Export_List : SeqAlgebra.Seq;
                                    The_Heap    : Heap.HeapRecord) return Dictionary.Symbol is
      Member : SeqAlgebra.MemberOfSeq;
      Sym    : Dictionary.Symbol;
   begin
      Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
      if SeqAlgebra.IsNullMember (Member) then
         Sym := Dictionary.NullSymbol;
      else
         Sym :=
           Dictionary.ConvertSymbolRef
           (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                   M        => Member)));
      end if;
      return Sym;
   end Get_First_Valid_Export;

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

   procedure Copy_Imports
     (Abstraction        : in Dictionary.Abstractions;
      Export_List        : in SeqAlgebra.Seq;
      First_Valid_Export : in Dictionary.Symbol;
      Subprog_Sym        : in Dictionary.Symbol;
      The_Heap           : in Heap.HeapRecord)
   --# global in out Dictionary.Dict;
   --# derives Dictionary.Dict from *,
   --#                              Abstraction,
   --#                              Export_List,
   --#                              First_Valid_Export,
   --#                              Subprog_Sym,
   --#                              The_Heap;
   is
      Member : SeqAlgebra.MemberOfSeq;
   begin
      Member := SeqAlgebra.FirstMember (The_Heap, Export_List);
      if not SeqAlgebra.IsNullMember (Member) then
         -- there is at leat one valid export, we want to loop through rest
         loop
            Member := SeqAlgebra.NextMember (The_Heap, Member);
            exit when SeqAlgebra.IsNullMember (Member);
            Dictionary.CopyDependencyList
              (Abstraction,
               Subprog_Sym,
               First_Valid_Export,
               Dictionary.ConvertSymbolRef
                 (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                         M        => Member))));
         end loop;
      end if;
   end Copy_Imports;

begin -- Create_Full_Dependency
   First_Valid_Export := Get_First_Valid_Export (Export_List => Export_List,
                                                 The_Heap    => The_Heap);
   Member             := SeqAlgebra.FirstMember (The_Heap, Import_List);
   while not SeqAlgebra.IsNullMember (Member) loop
      Import :=
        Dictionary.ConvertSymbolRef (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => The_Heap,
                                                                                            M        => Member)));
      --# accept Flow, 41, "Expected stable expression";
      if not Dictionary.Is_Null_Symbol (First_Valid_Export) then
         --# end accept;
         Dictionary.AddDependency
           (Abstraction     => Abstraction,
            Comp_Unit       => ContextManager.Ops.Current_Unit,
            TheProcedure    => Subprog_Sym,
            TheExport       => First_Valid_Export,
            TheImport       => Import,
            ImportReference => Dictionary.Location'(Start_Position => Node_Pos,
                                                    End_Position   => Node_Pos));
      else -- no valid export to associate with but mark to avoid knock-on errors
         Dictionary.ForceImport
           (Abstraction,
            Subprog_Sym,
            Import,
            Dictionary.Location'(Start_Position => Node_Pos,
                                 End_Position   => Node_Pos));
      end if;
      Member := SeqAlgebra.NextMember (The_Heap, Member);
   end loop;
   Copy_Imports
     (Abstraction        => Abstraction,
      Export_List        => Export_List,
      First_Valid_Export => First_Valid_Export,
      Subprog_Sym        => Subprog_Sym,
      The_Heap           => The_Heap);
end Create_Full_Dependency;
