-------------------------------------------------------------------------------
-- (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.
--
--=============================================================================

--------------------------------------------------------------------------------
-- RefList
--
-- Description:
--
-- The Reflist package provides a mechanism for storing node-based flow relations
-- more efficiently.  The actual relations are stored in the Heap and related
-- to a syntax node by means of a hash table.
-- See package spec.
--
-- Operation
--
-- The Reflist works in two parts.  The first is concerned with creating or
-- locating a KeyCell.  The KeyCell is a heap atom which is the start point for
-- the data structures required to describe the flow relations.  The KeyCell can
-- be found given a syntax node.  The second part of the operation is concerned
-- with adding or interrogating the data structures given a KeyCell as a
-- starting point.
--
-- KeyCell operations
--
-- The package contains an array called "Table" which is an array of Heap atoms.
-- It is initialized to all zeros (all null atoms).  Finding a KeyCell starts
-- with using a simple modulo hash function on an integer representation of the
-- syntax node; this yields an Index into the Table.  If the indexed value is 0
-- then there is no KeyCell for that node; otherwise, the Table entry will be
-- the value of a heap atom.  The Avalue of the atom contains the node number.
-- If more than one node hashes to the same table index, a linked list of atoms
-- is created using their Apointers.  So searching for a KeyCell involves
-- finding the correct table entry, then walking down the APointers of the atom
-- at that table location until the Avalue of an atom matches the node we are
-- seeking.  The atom found is the KeyCell
--
-- Node --(hash)--------------------------+
--                                        |
--                 Table------------------V------------------------------------+
--                 |0|0|0|0|0|0|0|0|0|0|0|.|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|
--                 +----------------------|------------------------------------+
--                                        |
--                                      +-V-----------+
--                                      |Avalue = Node|
--                                      |APtr         |
--                                      +-|-----------+
--                                        |
--                                      +-V-----------+
--                                      |Avalue = Node|
--                                      |APtr = null  |
--                                      +-------------+
--
-- Data Structure Operations
--
-- Given a KeyCell we can find the associated information flows.
-- There are three cases:
-- (1) The node has a "null relation" (i.e. derives nothing from nothing")
-- (2) The node has an associated referenced variable list (i.e. it references
--     variables but has no exports; this is typical of Conditions) in the form
--     of a SeqAlgebra.Seq
-- (3) The node has one or more exports each of which has a (SeqAlgebra)
--     sequence of imports
--     from which it is derived.  The sequence may of course be empty for any
--     particualr export
--
-- These cases are represented as follows:
-- Null derives
--
--      KeyCell------+
--      | BPtr = null|
--      +------------+
--
-- RefList
--
--      KeyCell------+
--      | BPtr ------------------> Head of SeqAlgebra.Seq containing referenced
--      +------------+             variables
--
-- (Note that because Seqs are built using Aptrs, we can distinguish the above
--  case from the one that follows because the Bptr of the cell pointed to
--  ("head of..." above) will be null)
--
-- Export list
--
--      KeyCell------+            +-----------------+
--      | BPtr ------------------>|AValue = export1 |
--      +------------+            |BPtr ------------------> Head of Seq
--                                |APtr             |       containing imports
--                                +-|---------------+       for export1
--                                  |
--                                  V
--                                +-----------------+
--                                |AValue = export2 |
--                                |BPtr ------------------> Head of Seq
--                                |APtr = null      |       containing imports
--                                +-----------------+       for export2
--
--
--------------------------------------------------------------------------------

with ExaminerConstants;
with SP_Symbols;
with SystemErrors;

use type SP_Symbols.SP_Symbol;

package body RefList is

   HashDivider : constant Integer := HashMax + 1;

   procedure Init (Table : out HashTable) is
   begin
      Table := HashTable'(HashIndex => 0);
   end Init;

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

   function Hash (Node : STree.SyntaxNode) return HashIndex is
   begin
      return Natural (STree.NodeToRef (Node)) mod HashDivider;
   end Hash;

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

   function MatchingNode
     (TheHeap : Heap.HeapRecord;
      Node    : STree.SyntaxNode;
      Cell    : Heap.Atom)
     return    Boolean
   is
   begin
      return Natural (STree.NodeToRef (Node)) = Heap.AValue (TheHeap, Cell);
   end MatchingNode;

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

   procedure FindOrMakeKeyCell
     (Table   : in out HashTable;
      TheHeap : in out Heap.HeapRecord;
      Node    : in     STree.SyntaxNode;
      Cell    :    out Heap.Atom)
   --# global in out Statistics.TableUsage;
   --# derives Cell,
   --#         Table,
   --#         TheHeap               from Node,
   --#                                    Table,
   --#                                    TheHeap &
   --#         Statistics.TableUsage from *,
   --#                                    Node,
   --#                                    Table,
   --#                                    TheHeap;
   is
      Index               : HashIndex;
      SeekCell, LocalCell : Heap.Atom;
      Found               : Boolean;

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

      procedure SetNodeValue (Cell : in Heap.Atom)
      --# global in     Node;
      --#        in out TheHeap;
      --# derives TheHeap from *,
      --#                      Cell,
      --#                      Node;
      is
      begin
         Heap.UpdateAValue (TheHeap, Cell, Natural (STree.NodeToRef (Node)));
      end SetNodeValue;

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

   begin -- FindOrMakeKeyCell
      Index := Hash (Node);
      if Table (Index) = 0 then
         -- first use of this hash table position
         Heap.CreateAtom (TheHeap, LocalCell);
         SetNodeValue (LocalCell);
         Table (Index) := Natural (LocalCell);
         Cell          := LocalCell;
      else
         -- a hit - search linked list for match
         SeekCell := Heap.Atom (Table (Index));
         loop
            Found := MatchingNode (TheHeap, Node, SeekCell);
            exit when Found;
            exit when Heap.IsNullPointer (Heap.APointer (TheHeap, SeekCell));
            SeekCell := Heap.APointer (TheHeap, SeekCell);
         end loop;
         if Found then
            Cell := SeekCell;
         else -- add new Atom to end of hit list
            Heap.CreateAtom (TheHeap, LocalCell);
            SetNodeValue (LocalCell);
            Heap.UpdateAPointer (TheHeap, SeekCell, LocalCell);
            Cell := LocalCell;
         end if;
      end if;
   end FindOrMakeKeyCell;

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

   procedure FindKeyCell
     (Table   : in     HashTable;
      TheHeap : in     Heap.HeapRecord;
      Node    : in     STree.SyntaxNode;
      Cell    :    out Heap.Atom)
   --# derives Cell from Node,
   --#                   Table,
   --#                   TheHeap;
   is
      Index    : HashIndex;
      SeekCell : Heap.Atom;

   begin -- FindKeyCell
      Index    := Hash (Node);
      SeekCell := Heap.Atom (Table (Index));
      loop
         exit when MatchingNode (TheHeap, Node, SeekCell);
         if Heap.IsNullPointer (Heap.APointer (TheHeap, SeekCell)) then
            SystemErrors.Fatal_Error (Sys_Err => SystemErrors.Ref_List_Key_Cell_Missing,
                                      Msg     => "");
         end if;
         SeekCell := Heap.APointer (TheHeap, SeekCell);
      end loop;
      Cell := SeekCell;
   end FindKeyCell;

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

   procedure AddRelation
     (Table     : in out HashTable;
      TheHeap   : in out Heap.HeapRecord;
      Node      : in     STree.SyntaxNode;
      TheExport : in     Dictionary.Symbol;
      Imports   : in     SeqAlgebra.Seq)
   is
      KeyCell, ExportCell : Heap.Atom;

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

      procedure LinkImports (TheHeap : in out Heap.HeapRecord;
                             Cell    : in     Heap.Atom;
                             Imps    : in     SeqAlgebra.Seq)
      --# derives TheHeap from *,
      --#                      Cell,
      --#                      Imps;
      is
      begin
         Heap.UpdateBPointer (TheHeap, Cell, Heap.Atom (SeqAlgebra.SeqToNatural (Imps)));
      end LinkImports;

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

      procedure SetSymValue (TheHeap : in out Heap.HeapRecord;
                             Cell    : in     Heap.Atom;
                             Sym     : in     Dictionary.Symbol)
      --# derives TheHeap from *,
      --#                      Cell,
      --#                      Sym;
      is
      begin
         Heap.UpdateAValue (TheHeap, Cell, Natural (Dictionary.SymbolRef (Sym)));
      end SetSymValue;

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

   begin -- AddRelation
      FindOrMakeKeyCell (Table, TheHeap, Node,
                         -- to get
                         KeyCell);
      if Dictionary.Is_Null_Symbol (TheExport) then
         -- create simple referenced variable list
         LinkImports (TheHeap, KeyCell, Imports);
      else
         -- create export list with each export pointing at import list
         Heap.CreateAtom (TheHeap, ExportCell);
         Heap.UpdateAPointer (TheHeap, ExportCell, Heap.BPointer (TheHeap, KeyCell));
         Heap.UpdateBPointer (TheHeap, KeyCell, ExportCell);
         SetSymValue (TheHeap, ExportCell, TheExport);
         LinkImports (TheHeap, ExportCell, Imports);
      end if;
   end AddRelation;

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

   procedure AddNullRelation (Table   : in out HashTable;
                              TheHeap : in out Heap.HeapRecord;
                              Node    : in     STree.SyntaxNode) is
      UnusedKeyCell : Heap.Atom;

   begin
      --# accept F, 10, UnusedKeyCell, "UnusedKeyCell unused here" &
      --#        F, 33, UnusedKeyCell, "UnusedKeyCell unused here";
      FindOrMakeKeyCell (Table, TheHeap, Node,
                         -- to get
                         UnusedKeyCell);
      -- Don't want to link anything to B ptr of KeyCell to indicate it is a
      -- null relation.
   end AddNullRelation;

   -------------extractor functions-------------------------------

   function NodeHasExportList
     (Table   : in HashTable;
      TheHeap : in Heap.HeapRecord;
      Node    : in STree.SyntaxNode)
     return    Boolean
   is
      Index    : HashIndex;
      SeekCell : Heap.Atom;
      Found    : Boolean;
   begin
      Index := Hash (Node);
      if Table (Index) = 0 then -- no entry that matches Node
         Found := False;
      else
         -- a hit - search linked list for match
         SeekCell := Heap.Atom (Table (Index));
         loop
            Found := MatchingNode (TheHeap, Node, SeekCell);
            if Found then
               -- Here we have a valid KeyCell called SeekCell.  We need to
               -- validate that it is the KeyCell for a list of one or more
               -- exports rather than something else (such as a referenced
               -- variable list)
               Found := (not Heap.IsNullPointer (Heap.BPointer (TheHeap, SeekCell)))
                 and then
                 -- The KeyCell's BPtr points at something (either a RefList
                 -- or an Export)
                 (not Heap.IsNullPointer (Heap.BPointer (TheHeap, Heap.BPointer (TheHeap, SeekCell))));
               -- and that something is an export because its Bptr points at
               -- a list of imports (if it was a  RefList then the BPtr would be
               -- null)
               exit; -- no second chances, we either found it or we didn't
            end if;
            exit when -- no more possible KeyCells
              Heap.IsNullPointer (Heap.APointer (TheHeap, SeekCell));
            SeekCell := Heap.APointer (TheHeap, SeekCell); -- next KeyCell
         end loop;
      end if;
      return Found;
   end NodeHasExportList;

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

   function ExportHasDependencies (TheExport : in Heap.Atom;
                                   TheHeap   : in Heap.HeapRecord) return Boolean is
   begin
      return not Heap.IsNullPointer (Heap.BPointer (TheHeap, TheExport));
   end ExportHasDependencies;

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

   procedure FirstExport
     (Table     : in     HashTable;
      TheHeap   : in     Heap.HeapRecord;
      Node      : in     STree.SyntaxNode;
      TheExport :    out Heap.Atom)
   is
      KeyCell        : Heap.Atom;
      TheExportLocal : Heap.Atom;
   begin
      FindKeyCell (Table, TheHeap, Node,
                   -- to get
                   KeyCell);
      TheExportLocal := Heap.BPointer (TheHeap, KeyCell);

      -- There are two valid cases:
      -- (1) TheExportLocal is null (indicating that the node's flow relation
      --     is "derives ;"; or
      -- (2) TheExportLocal's BPointer isn't null (indicating that there is at
      --     least one actual export).
      -- The only remaining case that the data structure could allow is trying
      -- to get the first export when TheExportLocal is actually linked to a
      -- Reflist (a list of variables referenced by a Condition for example).
      -- We check the validity thus:
      SystemErrors.RT_Assert
        (C       => Heap.IsNullPointer (TheExportLocal) -- case 1
           or else (not Heap.IsNullPointer (Heap.BPointer (TheHeap, TheExportLocal))),
         Sys_Err => SystemErrors.Other_Internal_Error,
         Msg     => "FirstExport of a RefList Node is empty");

      TheExport := TheExportLocal;
   end FirstExport;

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

   function NextExport (TheHeap   : Heap.HeapRecord;
                        TheExport : Heap.Atom) return Heap.Atom is
   begin
      return Heap.APointer (TheHeap, TheExport);
   end NextExport;

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

   function DependencyList (TheHeap   : Heap.HeapRecord;
                            TheExport : Heap.Atom) return SeqAlgebra.Seq is
   begin
      return SeqAlgebra.NaturalToSeq (Natural (Heap.BPointer (TheHeap, TheExport)));
   end DependencyList;

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

   procedure ReferencedVarList
     (Table   : in     HashTable;
      TheHeap : in     Heap.HeapRecord;
      Node    : in     STree.SyntaxNode;
      Seq     :    out SeqAlgebra.Seq)
   is
      KeyCell     : Heap.Atom;
      SeqOrExport : Heap.Atom;
   begin
      FindKeyCell (Table, TheHeap, Node,
                   -- to get
                   KeyCell);
      SeqOrExport := Heap.BPointer (TheHeap, KeyCell);
      -- If we have wrongly (in terms of the precondition) called this procedure
      -- on a node with exports then SeqOrExport will not be the referenced
      -- variable list we were hoping for but the head of a list of exports.
      -- We can tell if this is the case by checking the Bptr of the cell;
      -- it will be null if we have the list we are seeking and not null if we
      -- have got an export by mistake
      SystemErrors.RT_Assert
        (C       => Heap.IsNullPointer (Heap.BPointer (TheHeap, SeqOrExport)),
         Sys_Err => SystemErrors.Other_Internal_Error,
         Msg     => "ReferencedVariableList called on a node which has exports");

      Seq := SeqAlgebra.NaturalToSeq (Natural (SeqOrExport));
   end ReferencedVarList;

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

   procedure AllReferencedVariables
     (Table   : in     HashTable;
      TheHeap : in out Heap.HeapRecord;
      Node    : in     STree.SyntaxNode;
      Seq     :    out SeqAlgebra.Seq)
   is
      AllRefSeq : SeqAlgebra.Seq;
      AnExport  : Heap.Atom;
      NullAtom  : constant Heap.Atom := Heap.Atom (0);
   begin
      if NodeHasExportList (Table, TheHeap, Node) then
         -- create a set to union all imports into
         SeqAlgebra.CreateSeq (TheHeap, AllRefSeq);
         -- loop through exports
         FirstExport (Table, TheHeap, Node,
                      -- to get
                      AnExport);
         while AnExport /= NullAtom loop
            -- union imports of each export
            SeqAlgebra.AugmentSeq (TheHeap, AllRefSeq, DependencyList (TheHeap, AnExport));
            -- next export
            AnExport := NextExport (TheHeap, AnExport);
         end loop;
         -- return union
         Seq := AllRefSeq;

      else
         -- Must just be a list of referenced variables
         -- so just return it.
         ReferencedVarList (Table, TheHeap, Node, Seq);
      end if;
   end AllReferencedVariables;

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

   -- function returns true if Sym is the symbol of a record variable, or
   -- a subcomponent of a record and if it is not a leaf in the component
   -- data structure
   function IsRecordVarOrComponent (ComponentData : ComponentManager.ComponentData;
                                    Sym           : Dictionary.Symbol) return Boolean
   --# global in Dictionary.Dict;
   is
   begin
      return ((Dictionary.Is_Variable (Sym) and then Dictionary.TypeIsRecord (Dictionary.GetType (Sym)))
              or else Dictionary.IsSubcomponent (Sym))
        and then ComponentManager.HasChildren (ComponentData, ComponentManager.GetComponentNode (ComponentData, Sym));
   end IsRecordVarOrComponent;

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

   procedure ExpandSeq
     (ComponentData : in     ComponentManager.ComponentData;
      TheSeq        : in     SeqAlgebra.Seq;
      TheHeap       : in out Heap.HeapRecord)
   is
      ExpandedSeq               : SeqAlgebra.Seq;
      LeafSeq                   : SeqAlgebra.Seq;
      NextMember, CurrentMember : SeqAlgebra.MemberOfSeq;
      Sym                       : Dictionary.Symbol;

   begin -- ExpandSeq
      SeqAlgebra.CreateSeq (TheHeap, ExpandedSeq);
      CurrentMember := SeqAlgebra.FirstMember (TheHeap, TheSeq);
      while not SeqAlgebra.IsNullMember (CurrentMember) loop
         NextMember := SeqAlgebra.NextMember (TheHeap, CurrentMember);

         Sym :=
           Dictionary.ConvertSymbolRef
           (ExaminerConstants.RefType (SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                                                   M        => CurrentMember)));

         if IsRecordVarOrComponent (ComponentData, Sym) then
            ComponentManager.GetLeaves (TheHeap, ComponentData, ComponentManager.GetComponentNode (ComponentData, Sym),
                                        -- to get
                                        LeafSeq);
            SeqAlgebra.AugmentSeq (TheHeap, ExpandedSeq,
                                   -- with
                                   LeafSeq);
            SeqAlgebra.RemoveMember (TheHeap, TheSeq, SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                                                                  M        => CurrentMember));
         end if;

         CurrentMember := NextMember;
      end loop;
      SeqAlgebra.AugmentSeq (TheHeap, TheSeq,
                             -- with
                             ExpandedSeq);
      SeqAlgebra.DisposeOfSeq (TheHeap, ExpandedSeq);
   end ExpandSeq;

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

   procedure ExpandToComponentEntities
     (ComponentData : in     ComponentManager.ComponentData;
      Table         : in     HashTable;
      TheHeap       : in out Heap.HeapRecord)
   is
      KeyCell         : Heap.Atom;
      FirstExportAtom : Heap.Atom;

      ---------

      function HasRelation (KeyCell : in Heap.Atom) return Boolean
      --# global in STree.Table;
      --#        in TheHeap;
      is
         NodeType : SP_Symbols.SP_Symbol;
      begin
         NodeType :=
           STree.Syntax_Node_Type (Node => STree.RefToNode (ExaminerConstants.RefType (Heap.AValue (TheHeap, KeyCell))));
         return NodeType = SP_Symbols.assignment_statement
           or else NodeType = SP_Symbols.loop_parameter_specification
           or else NodeType = SP_Symbols.procedure_call_statement;
      end HasRelation;

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

      procedure ExpandRelation (FirstExportAtom : in Heap.Atom)
      --# global in     ComponentData;
      --#        in     Dictionary.Dict;
      --#        in out Statistics.TableUsage;
      --#        in out TheHeap;
      --# derives Statistics.TableUsage,
      --#         TheHeap               from *,
      --#                                    ComponentData,
      --#                                    Dictionary.Dict,
      --#                                    FirstExportAtom,
      --#                                    TheHeap;
      is
         CurrentExportAtom, NextExportAtom : Heap.Atom;
         Dependencies                      : SeqAlgebra.Seq;
         CurrentExportSym                  : Dictionary.Symbol;

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

         procedure ExpandExportList
           (CurrentExportAtom, NextExportAtom : in Heap.Atom;
            CurrentExportSym                  : in Dictionary.Symbol;
            Dependencies                      : in SeqAlgebra.Seq)
         --# global in     ComponentData;
         --#        in out Statistics.TableUsage;
         --#        in out TheHeap;
         --# derives Statistics.TableUsage,
         --#         TheHeap               from *,
         --#                                    ComponentData,
         --#                                    CurrentExportAtom,
         --#                                    CurrentExportSym,
         --#                                    Dependencies,
         --#                                    NextExportAtom,
         --#                                    TheHeap;
         is
            ExportLeaves           : SeqAlgebra.Seq;
            CurrentExportMember    : SeqAlgebra.MemberOfSeq;
            CurrentExportAtomLocal : Heap.Atom;
            NewAtom                : Heap.Atom;
         begin
            CurrentExportAtomLocal := CurrentExportAtom;
            ComponentManager.GetLeaves
              (TheHeap,
               ComponentData,
               ComponentManager.GetComponentNode (ComponentData, CurrentExportSym),
               -- to get
               ExportLeaves);
            -- replace cell value of current export with first component
            CurrentExportMember := SeqAlgebra.FirstMember (TheHeap, ExportLeaves);
            Heap.UpdateAValue
              (TheHeap,
               CurrentExportAtomLocal,
               -- with
               SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                           M        => CurrentExportMember));

            CurrentExportMember := SeqAlgebra.NextMember (TheHeap, CurrentExportMember);
            while not SeqAlgebra.IsNullMember (CurrentExportMember) loop
               -- link in other expanded export leaves
               -- first create new export cell
               Heap.CreateAtom (TheHeap, NewAtom);
               Heap.UpdateAValue (TheHeap, NewAtom,
                                  -- with
                                  SeqAlgebra.Value_Of_Member (The_Heap => TheHeap,
                                                              M        => CurrentExportMember));
               -- link it to the dependencies
               Heap.UpdateBPointer (TheHeap, NewAtom, Heap.Atom (SeqAlgebra.SeqToNatural (Dependencies)));
               -- link it into the sequence of exports
               Heap.UpdateAPointer (TheHeap, CurrentExportAtomLocal, NewAtom);
               Heap.UpdateAPointer (TheHeap, NewAtom, NextExportAtom);
               CurrentExportAtomLocal := NewAtom;
               -- get next expanded export leaf
               CurrentExportMember := SeqAlgebra.NextMember (TheHeap, CurrentExportMember);
            end loop;
            SeqAlgebra.DisposeOfSeq (TheHeap, ExportLeaves);
         end ExpandExportList;

      begin -- ExpandRelation
         CurrentExportAtom := FirstExportAtom;
         while not Heap.IsNullPointer (CurrentExportAtom) loop
            NextExportAtom := NextExport (TheHeap, CurrentExportAtom);

            Dependencies := DependencyList (TheHeap, CurrentExportAtom);

            ExpandSeq (ComponentData, Dependencies, TheHeap);
            CurrentExportSym :=
              Dictionary.ConvertSymbolRef (ExaminerConstants.RefType (Heap.AValue (TheHeap, CurrentExportAtom)));
            if IsRecordVarOrComponent (ComponentData, CurrentExportSym) then
               -- export needs expanding as well as import
               ExpandExportList (CurrentExportAtom, NextExportAtom, CurrentExportSym, Dependencies);
            end if;
            CurrentExportAtom := NextExportAtom;
         end loop;
      end ExpandRelation;

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

   begin -- ExpandToComponentEntities
      for I in HashIndex loop
         if Table (I) /= 0 then -- there is an entry to be processed
            KeyCell := Heap.Atom (Table (I));
            loop -- to process all cells that may be in clash list
               if HasRelation (KeyCell) then
                  FirstExportAtom := Heap.BPointer (TheHeap, KeyCell);
                  if not Heap.IsNullPointer (FirstExportAtom) then
                     ExpandRelation (FirstExportAtom);
                  end if;
               else -- just a sequence of imports
                  ExpandSeq (ComponentData, SeqAlgebra.NaturalToSeq (Natural (Heap.BPointer (TheHeap, KeyCell))), TheHeap);
               end if;
               KeyCell := Heap.APointer (TheHeap, KeyCell);
               exit when Heap.IsNullPointer (KeyCell);

            end loop;
         end if;
      end loop;
   end ExpandToComponentEntities;

end RefList;
