------------------------------------------------------------------------------
--                                                                          --
--                           POLYORB COMPONENTS                             --
--                                                                          --
--                C I A O . T R A N S L A T O R . S T A T E                 --
--                                                                          --
--                                 B o d y                                  --
--                                                                          --
--         Copyright (C) 1999-2012, Free Software Foundation, Inc.          --
--                                                                          --
-- This is free software;  you can redistribute it  and/or modify it  under --
-- terms of the  GNU General Public License as published  by the Free Soft- --
-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
-- sion.  This software is distributed in the hope  that it will be useful, --
-- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
-- TABILITY 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 and    --
-- a copy of the GCC Runtime Library Exception along with this program;     --
-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
-- <http://www.gnu.org/licenses/>.                                          --
--                                                                          --
--                  PolyORB is maintained by AdaCore                        --
--                     (email: sales@adacore.com)                           --
--                                                                          --
------------------------------------------------------------------------------

--  The internal state of the translator.
with Asis.Elements; use Asis.Elements;

with GNAT.HTable;

with Idl_Fe.Types; use Idl_Fe.Types;

package body CIAO.Translator.State is

   procedure Initialize_Translator_State
     (Category   : in     Unit_Categories;
      Unit       : in     Asis.Compilation_Unit;
      Repository : in     Node_Id;
      State      :    out Translator_State)
   is
   begin
      State.Repository    := Repository;
      State.Unit_Category := Category;
      State.Current_Node  := Repository;
   end Initialize_Translator_State;

   -----------------------------------------------------------
   -- Map_Info                                              --
   -- All the information recorded about the mapping        --
   -- of an Ada element.                                    --
   --                                                       --
   -- For an element that is part of the current library    --
   -- unit, the translation is defined by the Mapping       --
   -- Specification Document.                               --
   -- Additionally, for each withed unit, a translation     --
   -- for the unit declaration is registered. It designates --
   -- the corresponding N_Preprocessor_Include node.        --
   -----------------------------------------------------------

   type Map_Info is record
      Translation           : Node_Id := No_Node;
      Previous_Current_Node : Node_Id := No_Node;
   end record;
   --  All information we want to keep about the mapping
   --  of an Ada Element is stored as a Map_Info record.

   Nil_Map_Info : constant Map_Info :=
     (Translation           => No_Node,
      Previous_Current_Node => No_Node);

   -------------------------------------
   -- Elementary hash table accessors --
   -------------------------------------

   procedure Set_Map_Info (Element : Asis.Element; Info : Map_Info);
   pragma Inline (Set_Map_Info);
   --  Set the Map_Info for the Element.

   function Get_Map_Info  (Element : Asis.Element)
     return Map_Info;
   pragma Inline (Get_Map_Info);
   --  Retrieve the mapping information for an Element.
   --  If no information was set, Nil_Map_Info is returned.

   procedure Set_Origin (Node : Node_Id; Element : Asis.Element);
   pragma Inline (Set_Origin);
   --  Record the original ASIS element at the origin of Node.

   --------------------------------
   -- High-level state accessors --
   --------------------------------

   procedure Set_Translation
     (Element     : Asis.Element;
      Translation : Node_Id) is
      Info : Map_Info := Get_Map_Info (Element);
   begin
      Info.Translation := Translation;
      Set_Map_Info (Element, Info);
      Set_Origin (Translation, Element);
   end Set_Translation;

   procedure Set_Previous_Current_Node
     (Element               : Asis.Element;
      Previous_Current_Node : Node_Id) is
      Info : Map_Info := Get_Map_Info (Element);
   begin
      Info.Previous_Current_Node := Previous_Current_Node;
      Set_Map_Info (Element, Info);
   end Set_Previous_Current_Node;

   function Get_Translation (Element : Asis.Element)
     return Node_Id is
   begin
      return Get_Map_Info (Element).Translation;
   end Get_Translation;

   function Get_Previous_Current_Node (Element : Asis.Element)
     return Node_Id is
   begin
      return Get_Map_Info (Element).Previous_Current_Node;
   end Get_Previous_Current_Node;

   -------------------------------------------------------------------
   -- Implementation of the hash functions and hash table accessors --
   -------------------------------------------------------------------

   type Map_HTable_Header_Num is range 1 .. 256;

   function Hash_Element (E : Asis.Element)
     return Map_HTable_Header_Num;
   --  Hash function for an ASIS Element.

   function Hash_Element (E : Asis.Element)
     return Map_HTable_Header_Num is
   begin
      return Map_HTable_Header_Num
        (Integer (Map_HTable_Header_Num'First)
         + Asis.Elements.Hash (E)
         mod Asis.ASIS_Integer (Map_HTable_Header_Num'Last -
                           Map_HTable_Header_Num'First + 1));
   end Hash_Element;

   package Map_HTable is new GNAT.HTable.Simple_HTable
     (Header_Num => Map_HTable_Header_Num,
      Element    => Map_Info,
      No_Element => Nil_Map_Info,
      Key        => Asis.Element,
      Hash       => Hash_Element,
      Equal      => Asis.Elements.Is_Identical);
   --  A table that records a reference of the corresponding
   --  IDL node for any given Ada element (represented by an
   --  Ids.Id value). The Map_HTable is notionally part of the
   --  translator's state.

   procedure Set_Map_Info (Element : Asis.Element; Info : Map_Info) is
   begin
      Map_HTable.Set (Element, Info);
   end Set_Map_Info;

   function Get_Map_Info (Element : Asis.Element) return Map_Info is
   begin
      return Map_HTable.Get (Element);
   end Get_Map_Info;

   function Hash_Node_Id (N : Node_Id)
     return Map_HTable_Header_Num;
   --  Hash function for a node id.

   function Hash_Node_Id (N : Node_Id)
     return Map_HTable_Header_Num
   is
   begin
      return Map_HTable_Header_Num
        (Integer (Map_HTable_Header_Num'First)
         + Integer (N)
         mod Asis.ASIS_Integer (Map_HTable_Header_Num'Last -
                                Map_HTable_Header_Num'First + 1));
   end Hash_Node_Id;

   package Origin_HTable is new GNAT.HTable.Simple_HTable
     (Header_Num => Map_HTable_Header_Num,
      Element    => Asis.Element,
      No_Element => Asis.Nil_Element,
      Key        => Node_Id,
      Hash       => Hash_Node_Id,
      Equal      => "=");
   --  A table that records the original ASIS element corresponding
   --  to an IDL node. The Origin_HTable is notionally part of the
   --  translator's state.

   procedure Set_Origin (Node : Node_Id; Element : Asis.Element) is
   begin
      Origin_HTable.Set (Node, Element);
   end Set_Origin;

   function Get_Origin (Node : Node_Id) return Asis.Element is
   begin
      return Origin_HTable.Get (Node);
   end Get_Origin;

end CIAO.Translator.State;
