-------------------------------------------------------------------------------
-- (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)
procedure Add_Derives_Stream_Effects
  (Node_Pos    : in LexTokenManager.Token_Position;
   Subprog_Sym : in Dictionary.Symbol;
   Abstraction : in Dictionary.Abstractions)
is
   Export_It, Import_It   : Dictionary.Iterator;
   Export_Sym, Import_Sym : Dictionary.Symbol;
begin
   -- first scan exports for reference to out streams
   Export_It := Dictionary.FirstExport (Abstraction, Subprog_Sym);
   while not Dictionary.IsNullIterator (Export_It) loop
      Export_Sym := Dictionary.CurrentSymbol (Export_It);
      -- writes to an out streams are also implicit imports
      if Dictionary.GetOwnVariableOrConstituentMode (Export_Sym) = Dictionary.OutMode then
         Dictionary.AddDependency
           (Abstraction     => Abstraction,
            Comp_Unit       => ContextManager.Ops.Current_Unit,
            TheProcedure    => Subprog_Sym,
            TheExport       => Export_Sym,
            TheImport       => Export_Sym,
            ImportReference => Dictionary.Location'(Start_Position => Node_Pos,
                                                    End_Position   => Node_Pos));
      end if;
      Export_It := Dictionary.NextSymbol (Export_It);
   end loop;

   -- now scan imports for reads of in streams
   Import_It := Dictionary.FirstImport (Abstraction, Subprog_Sym);
   while not Dictionary.IsNullIterator (Import_It) loop
      Import_Sym := Dictionary.CurrentSymbol (Import_It);
      -- reads of in streams imply an update as well
      if Dictionary.GetOwnVariableOrConstituentMode (Import_Sym) = Dictionary.InMode then
         Dictionary.AddExport
           (Abstraction     => Abstraction,
            TheProcedure    => Subprog_Sym,
            TheExport       => Import_Sym,
            ExportReference => Dictionary.Location'(Start_Position => Node_Pos,
                                                    End_Position   => Node_Pos),
            Annotation      => Dictionary.Location'(Start_Position => Node_Pos,
                                                    End_Position   => Node_Pos));
         Dictionary.AddDependency
           (Abstraction     => Abstraction,
            Comp_Unit       => ContextManager.Ops.Current_Unit,
            TheProcedure    => Subprog_Sym,
            TheExport       => Import_Sym,
            TheImport       => Import_Sym,
            ImportReference => Dictionary.Location'(Start_Position => Node_Pos,
                                                    End_Position   => Node_Pos));
      end if;
      Import_It := Dictionary.NextSymbol (Import_It);
   end loop;
end Add_Derives_Stream_Effects;
