-- ============================================================================ -- >>>>>>>>>>>>>>>>>>>>>>>>>> ADA COMPILATION UNIT <<<<<<<<<<<<<<<<<<<<<<<<<<<< -- ============================================================================ -- -- NAME: Region_View -- -- BODY -- -- AUTHOR: Chuck Hobin -- General Research Corporation -- -- CHANGE HISTORY -- -- MM-DD-YY | Initials | Description -- ---------------------------------------------------------------------------- -- -- ============================================================================ with Asis_Error_Handling_Support; with Msg_Log; with Unchecked_Deallocation; package body Region_View is Cuid : constant String := "Region_View"; package Asis_D renames Asis.Declarations; package Asis_E renames Asis.Elements; package Asis_Rc renames Asis.Representation_Clauses; package Asis_S renames Asis.Statements; package Asis_Td renames Asis.Type_Definitions; package Asis_X renames Asis.Expressions; package Structures renames Region_View_Structures; function "=" (Left, Right : Region_Support.Region_Kinds) return Boolean renames Region_Support."="; function Declarative_Region_Kind (Region_Part_Kind : in Region_Support.Region_Kinds) return Structures.Declarative_Region_Kinds; procedure Add_Region_Part (Part : in Structures.Region_Part_Ptr; To : in out Structures.Declarative_Region_Ptr); procedure Append (Item : in Structures.Region_Part_Ptr; As_Child_Of : in out Structures.Region_Part_Ptr); procedure Append (Item : in Structures.Declarative_Region_Ptr; As_Child_Of : in out Structures.Declarative_Region_Ptr); ------------------------------------------------------------------------------- procedure Free is new Unchecked_Deallocation (Structures.Region_Part, Structures.Region_Part_Ptr); procedure Free is new Unchecked_Deallocation (Structures.Region_Part_List_Element, Structures.Region_Part_List); procedure Free is new Unchecked_Deallocation (Structures.Declarative_Region, Structures.Declarative_Region_Ptr); procedure Free is new Unchecked_Deallocation (Structures.Declarative_Region_List_Element, Structures.Declarative_Region_List); procedure Free is new Unchecked_Deallocation (Structures.Comp_Unit, Structures.Comp_Unit_Ptr); procedure Free is new Unchecked_Deallocation (Structures.Comp_Unit_List_Element, Structures.Comp_Unit_List); procedure Free_View is new Unchecked_Deallocation (Structures.Region_View_Record, Structures.Region_View); ------------------------------------------------------------------------------- procedure Initialize (The_View : in out Region_View_Structures.Region_View) is begin Free (The_View); The_View := new Region_View_Structures.Region_View_Record; end Initialize; ------------------------------------------------------------------------------- procedure Start_Comp_Unit (The_Unit : Asis.Compilation_Unit; View_To_Update : in out Region_View_Structures.Region_View) is Comp_Unit : Structures.Comp_Unit_Ptr; New_Element : Structures.Comp_Unit_List; List : Structures.Comp_Unit_List; function "=" (Left, Right : Structures.Comp_Unit_List) return Boolean renames Structures."="; begin Comp_Unit := new Structures.Comp_Unit; Comp_Unit.Asis_Comp_Unit := The_Unit; View_To_Update.Current_Comp_Unit := Comp_Unit; -- Append the new comp unit to the view's comp unit list. New_Element := new Structures.Comp_Unit_List_Element; New_Element.The_Unit := Comp_Unit; if View_To_Update.Comp_Units = null then View_To_Update.Comp_Units := New_Element; else List := View_To_Update.Comp_Units; loop exit when List.Next = null; List := List.Next; end loop; List.Next := New_Element; end if; end Start_Comp_Unit; ------------------------------------------------------------------------------- procedure Enter_Region (The_Region : Region_Support.Region; View_To_Update : in out Region_View_Structures.Region_View) is Puid : constant String := "Enter_Region"; -- This procedure has the following effects: -- -- * A new region part structure is created, attached into the -- region part tree of the current comp unit, and pushed on the -- region part stack. -- -- * The declarative region that this region part belongs to -- is identified. A new declarative region structure is created -- and attached into the declarative region tree of the view -- if the structure does not already exist. -- -- * The region part is assigned to the appropriate field of the -- declarative region structure. -- -- * The region part's head element is associated with the -- declarative region in the head element map. Head_Element : Asis.Element; The_Region_Part : Structures.Region_Part_Ptr; The_Declarative_Region : Structures.Declarative_Region_Ptr; Parent_Region_Part : Structures.Region_Part_Ptr; Parent_Declarative_Region : Structures.Declarative_Region_Ptr; Region_Kind : Region_Support.Region_Kinds; -- Local subprogram : Create_Declarative_Region -- -- Given a region part, create a new declarative region structure -- an attach it into the declarative region tree. procedure Create_Declarative_Region is begin The_Declarative_Region := new Structures.Declarative_Region (Kind => Declarative_Region_Kind (Region_Kind)); The_Declarative_Region.Defining_Element := Head_Element; -- We use the innermost enclosing region part (i.e., -- the one on top of the region part stack) to -- determine the parent declarative region. If the -- enclosing region part has kind A_Compilation_Unit, -- the new declarative region is enclosed only by the -- declarative region of package Standard (LRM 8.1(11)); -- in this case, the new declarative region becomes the -- root of the declarative region tree and has no parent. -- Otherwise, we use the head element of the enclosing -- region part to find the parent declarative region. Parent_Region_Part := Structures.Rp_Stack.Top_Of (View_To_Update.Region_Part_Stack); if Region_Support.Kind (Parent_Region_Part.Region) = Region_Support.A_Compilation_Unit then View_To_Update.Declarative_Region_Tree := The_Declarative_Region; else -- NOTE: the following lookup will never fail because of -- our assertion that all region parts previously encountered -- have a valid entry in the map. Parent_Declarative_Region := Structures.Element_Region_Map.Range_Of (Region_Support.Head_Element (Parent_Region_Part.Region), In_The_Map => View_To_Update.Head_Element_Map); The_Declarative_Region.Parent := Parent_Declarative_Region; Append (The_Declarative_Region, As_Child_Of => Parent_Declarative_Region); end if; end Create_Declarative_Region; begin -- Enter_Region if Region_Support.Kind (The_Region) = Region_Support.A_Compilation_Unit then -- The compilation unit region part does not have an -- associated declarative region. Its only role is -- to serve as the conceptual root of the comp unit's -- region part tree. The_Region_Part := new Structures.Region_Part' (Region => The_Region, Parent => null, Children => null); View_To_Update.Current_Comp_Unit.Region_Part_Tree := The_Region_Part; -- Push the region part on the region part stack, identifying it as -- the innermost region part being traversed. Structures.Rp_Stack.Push (The_Region_Part, On_The_Stack => View_To_Update.Region_Part_Stack); return; end if; -- All other region kinds are parts of declarative regions. The_Region_Part := new Structures.Region_Part' (Region => The_Region, Parent => null, Children => null); Head_Element := Region_Support.Head_Element (The_Region); Region_Kind := Region_Support.Kind (The_Region); begin -- Get the declarative region associated with the region -- part's head element, if one already exists. (This can -- occur in the case of two or more region parts sharing -- the same head element,.e.g., the visible and private -- parts of a package declaration.) The_Declarative_Region := Structures.Element_Region_Map.Range_Of (Head_Element, In_The_Map => View_To_Update.Head_Element_Map); exception when Structures.Element_Region_Map.Domain_Is_Not_Bound => -- There is no associated declarative region. If -- the head element is one that *defines* a -- declarative region, we create a new declarative -- region object and attach into the declarative -- region tree. if Region_Support.Defines_A_Declarative_Region (Head_Element) then Create_Declarative_Region; else -- The head element does NOT define a declarative -- region. The head element must be either: -- -- 1) a declaration that is a *secondary* declaration of -- a program unit or a type (e.g., a package body), -- -- 2) an accept statement, or -- -- 3) a record representation clause. -- -- Thus, this region part is part of an existing -- declarative region. We find the declarative region -- by getting the corresponding first declaration of the -- head element (which itself should be the head element -- of some other region part) and using it to perform a -- lookup in the head element map. declare First_Declaration : Asis.Declaration; begin if Asis_E."=" (Asis_E.Element_Kind (Head_Element), Asis_E.A_Statement) and then Asis_S."=" (Asis_S.Kind (Head_Element), Asis_S.An_Accept_Statement) then First_Declaration := Asis_S.Accepted_Entry (Head_Element); elsif Asis_E."=" (Asis_E.Element_Kind (Head_Element), Asis_E.A_Representation_Clause) and then Asis_Rc."=" (Asis_Rc.Kind (Head_Element), Asis_Rc.A_Record_Representation_Clause) then First_Declaration := Asis_X.Name_Declaration (Asis_Rc. Record_Representation_Clause_Type_Simple_Name (Head_Element)); -- The following also works on Apex ASIS: -- -- First_Declaration := Asis_Td.Type_Definition_Declaration -- (Asis_Rc.Associated_Type (Head_Element)); -- -- When the first declaration of the record is an incomplete/ -- private type declaration, that declaration (not the -- full declaration) is returned, which is what we want. -- However, since the documentation for -- Type_Definition_Declaration does not explicitly -- say it should work this way, some implementations -- might return the full declaration, instead. Thus, -- I chose a different approach to be safe. else -- Head_Element is a declaration. First_Declaration := Asis_X.Name_Declaration (Asis_D.Names (Head_Element) (1)); end if; The_Declarative_Region := Structures.Element_Region_Map.Range_Of (First_Declaration, In_The_Map => View_To_Update.Head_Element_Map); exception -- If Asis problems occur, or if the lookup using -- First_Declaration fails, then we won't be able -- to successfully locate the declarative region. -- So that we preserve the assertion below, -- we create a new (erroneous) declarative region. -- This will allow view construction to complete. when Asis.Asis_Failed | Asis. Asis_Inappropriate_Element => Asis_Error_Handling_Support.Log_Element_Error (Head_Element, Cuid, Puid); Msg_Log.Put_Msg (Msg_Log.Debug, "Error occurred on attempt to find first definition of head element"); Create_Declarative_Region; when Structures.Element_Region_Map. Domain_Is_Not_Bound => Msg_Log.Put_Msg_Internal (Cuid, Puid, "Internal error occurred - attempting to continue (diagnosis follows)"); Msg_Log.Put_Msg (Msg_Log.Debug, Asis_Error_Handling_Support.Element_Info (Head_Element)); Msg_Log.Put_Msg (Msg_Log.Debug, "Declarative region lookup for secondary region part failed"); Create_Declarative_Region; end; end if; Structures.Element_Region_Map.Bind (The_Domain => Head_Element, And_The_Range => The_Declarative_Region, In_The_Map => View_To_Update.Head_Element_Map); end; -- ASSERT: We have now identified the declarative region that this -- region part is part of, and have recorded this association -- in the head element map. -- Assign the region part to the appropriate field of the -- declarative region structure. Add_Region_Part (The_Region_Part, To => The_Declarative_Region); -- Attach the region part into the region part tree. Parent_Region_Part := Structures.Rp_Stack.Top_Of (View_To_Update.Region_Part_Stack); The_Region_Part.Parent := Parent_Region_Part; Append (The_Region_Part, As_Child_Of => Parent_Region_Part); -- Push the region part on the region part stack, identifying it as -- the innermost region part being traversed. Structures.Rp_Stack.Push (The_Region_Part, On_The_Stack => View_To_Update.Region_Part_Stack); end Enter_Region; ------------------------------------------------------------------------------- procedure Leave_Region (The_Region : Region_Support.Region; View_To_Update : in out Region_View_Structures.Region_View) is begin Structures.Rp_Stack.Pop (View_To_Update.Region_Part_Stack); end Leave_Region; ------------------------------------------------------------------------------- procedure Finish_Comp_Unit (The_Unit : Asis.Compilation_Unit; View_To_Update : in out Region_View_Structures.Region_View) is begin View_To_Update.Current_Comp_Unit := null; end Finish_Comp_Unit; ------------------------------------------------------------------------------- procedure Free (The_View : in out Region_View_Structures.Region_View) is use Structures; procedure Free_Region_Part (The_Part : in out Structures.Region_Part_Ptr); procedure Free_Region (The_Region : in out Structures.Declarative_Region_Ptr); procedure Free_Region_Part_List (The_List : in out Structures.Region_Part_List) is begin if The_List /= null then Free_Region_Part_List (The_List.Next); Free_Region_Part (The_List.Region_Part); Free (The_List); end if; end Free_Region_Part_List; procedure Free_Region_Part (The_Part : in out Structures.Region_Part_Ptr) is begin if The_Part /= null then Free_Region_Part_List (The_Part.Children); Free (The_Part); end if; end Free_Region_Part; procedure Free_Region_List (The_List : in out Structures.Declarative_Region_List) is begin if The_List /= null then Free_Region_List (The_List.Next); Free_Region (The_List.Declarative_Region); Free (The_List); end if; end Free_Region_List; procedure Free_Region (The_Region : in out Structures.Declarative_Region_Ptr) is begin if The_Region /= null then Free_Region_List (The_Region.Children); Free (The_Region); end if; end Free_Region; procedure Free_Comp_Unit_List (The_List : in out Structures.Comp_Unit_List) is begin if The_List /= null then Free_Comp_Unit_List (The_List.Next); Free_Region_Part (The_List.The_Unit.Region_Part_Tree); Free (The_List); end if; end Free_Comp_Unit_List; begin -- Free if The_View /= null then Free_Region (The_View.Declarative_Region_Tree); Free_Comp_Unit_List (The_View.Comp_Units); Element_Region_Map.Clear (The_View.Head_Element_Map); Rp_Stack.Clear (The_View.Region_Part_Stack); Free_View (The_View); end if; end Free; ------------------------------------------------------------------------------- function Declarative_Region_Kind (Region_Part_Kind : in Region_Support.Region_Kinds) return Structures.Declarative_Region_Kinds is The_Kind : Structures.Declarative_Region_Kinds; begin case Region_Part_Kind is when Region_Support.A_Compilation_Unit => null; -- SHOULD NEVER GET HERE! when Region_Support.A_Record_Type_Declaration => The_Kind := Structures.A_Record_Type; when Region_Support.An_Incomplete_Type_Declaration => The_Kind := Structures.A_Record_Type; when Region_Support.A_Private_Type_Declaration => The_Kind := Structures.A_Record_Type; when Region_Support.A_Package_Specification_Visible_Part => The_Kind := Structures.A_Package; when Region_Support.A_Package_Specification_Private_Part => The_Kind := Structures.A_Package; when Region_Support.A_Package_Body => The_Kind := Structures.A_Package; when Region_Support.A_Procedure_Specification => The_Kind := Structures.A_Subprogram; when Region_Support.A_Procedure_Body => The_Kind := Structures.A_Subprogram; when Region_Support.A_Function_Specification => The_Kind := Structures.A_Subprogram; when Region_Support.A_Function_Body => The_Kind := Structures.A_Subprogram; when Region_Support.A_Procedure_Rename_Declaration => The_Kind := Structures.A_Rename; when Region_Support.A_Function_Rename_Declaration => The_Kind := Structures.A_Rename; when Region_Support.A_Generic_Package_Formal_Part => The_Kind := Structures.A_Generic_Package; when Region_Support.A_Generic_Package_Specification_Visible_Part => The_Kind := Structures.A_Generic_Package; when Region_Support.A_Generic_Package_Specification_Private_Part => The_Kind := Structures.A_Generic_Package; when Region_Support.A_Generic_Procedure_Formal_Part => The_Kind := Structures.A_Generic_Subprogram; when Region_Support.A_Generic_Procedure_Specification_Part => The_Kind := Structures.A_Generic_Subprogram; when Region_Support.A_Generic_Function_Formal_Part => The_Kind := Structures.A_Generic_Subprogram; when Region_Support.A_Generic_Function_Specification_Part => The_Kind := Structures.A_Generic_Subprogram; when Region_Support.A_Task_Declaration => The_Kind := Structures.A_Task; when Region_Support.A_Task_Body => The_Kind := Structures.A_Task; when Region_Support.A_Task_Type_Declaration => The_Kind := Structures.A_Task; when Region_Support.An_Entry_Declaration => The_Kind := Structures.An_Entry; when Region_Support.A_Procedure_Body_Stub => The_Kind := Structures.A_Subprogram; when Region_Support.A_Function_Body_Stub => The_Kind := Structures.A_Subprogram; when Region_Support.A_Package_Body_Stub => The_Kind := Structures.A_Package; when Region_Support.A_Task_Body_Stub => The_Kind := Structures.A_Task; when Region_Support.A_Generic_Formal_Private_Type_Declaration => The_Kind := Structures.A_Generic_Formal_Private_Type; when Region_Support.A_Generic_Formal_Procedure_Specification => The_Kind := Structures.A_Generic_Formal_Subprogram; when Region_Support.A_Generic_Formal_Function_Specification => The_Kind := Structures.A_Generic_Formal_Subprogram; when Region_Support.A_For_Loop_Statement => The_Kind := Structures.A_Loop_Statement; when Region_Support.A_While_Loop_Statement => The_Kind := Structures.A_Loop_Statement; when Region_Support.A_Simple_Loop_Statement => The_Kind := Structures.A_Loop_Statement; when Region_Support.A_Block_Statement => The_Kind := Structures.A_Block_Statement; when Region_Support.An_Accept_Statement => The_Kind := Structures.An_Entry; when Region_Support.A_Record_Representation_Clause => The_Kind := Structures.A_Record_Type; end case; return The_Kind; end Declarative_Region_Kind; ------------------------------------------------------------------------------- procedure Add_Region_Part (Part : in Structures.Region_Part_Ptr; To : in out Structures.Declarative_Region_Ptr) is Region_Part_Kind : Region_Support.Region_Kinds; begin Region_Part_Kind := Region_Support.Kind (Part.Region); case To.Kind is when Structures.A_Package => case Region_Part_Kind is when Region_Support.A_Package_Specification_Visible_Part => To.Package_Visible_Region_Part := Part; when Region_Support.A_Package_Specification_Private_Part => To.Package_Private_Region_Part := Part; when Region_Support.A_Package_Body_Stub => To.Package_Stub_Region_Part := Part; when Region_Support.A_Package_Body => To.Package_Body_Region_Part := Part; when others => null; end case; when Structures.A_Generic_Package => case Region_Part_Kind is when Region_Support. A_Generic_Package_Specification_Visible_Part => To.Package_Visible_Region_Part := Part; when Region_Support. A_Generic_Package_Specification_Private_Part => To.Package_Private_Region_Part := Part; when Region_Support.A_Package_Body_Stub => To.Package_Stub_Region_Part := Part; when Region_Support.A_Package_Body => To.Package_Body_Region_Part := Part; when Region_Support.A_Generic_Package_Formal_Part => To.Generic_Package_Formal_Part := Part; when others => null; end case; when Structures.A_Subprogram => case Region_Part_Kind is when Region_Support.A_Procedure_Specification | Region_Support.A_Function_Specification => To.Subprogram_Spec_Region_Part := Part; when Region_Support.A_Procedure_Body_Stub | Region_Support.A_Function_Body_Stub => To.Subprogram_Stub_Region_Part := Part; when Region_Support.A_Procedure_Body | Region_Support.A_Function_Body => To.Subprogram_Body_Region_Part := Part; when others => null; end case; when Structures.A_Generic_Subprogram => case Region_Part_Kind is when Region_Support.A_Generic_Procedure_Specification_Part | Region_Support.A_Generic_Function_Specification_Part => To.Subprogram_Spec_Region_Part := Part; when Region_Support.A_Procedure_Body_Stub | Region_Support.A_Function_Body_Stub => To.Subprogram_Stub_Region_Part := Part; when Region_Support.A_Procedure_Body | Region_Support.A_Function_Body => To.Subprogram_Body_Region_Part := Part; when Region_Support.A_Generic_Procedure_Formal_Part | Region_Support.A_Generic_Function_Formal_Part => To.Generic_Subprogram_Formal_Part := Part; when others => null; end case; when Structures.A_Task => case Region_Part_Kind is when Region_Support.A_Task_Declaration | Region_Support.A_Task_Type_Declaration => To.Task_Spec_Region_Part := Part; when Region_Support.A_Task_Body_Stub => To.Task_Stub_Region_Part := Part; when Region_Support.A_Task_Body => To.Task_Body_Region_Part := Part; when others => null; end case; when Structures.An_Entry => case Region_Part_Kind is when Region_Support.An_Entry_Declaration => To.Entry_Declaration_Region_Part := Part; when Region_Support.An_Accept_Statement => declare New_Element : Structures.Region_Part_List; List : Structures.Region_Part_List; function "=" (Left, Right : Structures.Region_Part_List) return Boolean renames Structures."="; begin New_Element := new Structures.Region_Part_List_Element; New_Element.Region_Part := Part; if To.Accept_Statement_Region_Parts = null then To.Accept_Statement_Region_Parts := New_Element; else -- append to list. List := To.Accept_Statement_Region_Parts; loop exit when List.Next = null; List := List.Next; end loop; List.Next := New_Element; end if; end; when others => null; end case; when Structures.A_Record_Type => case Region_Part_Kind is when Region_Support.A_Record_Type_Declaration => To.Record_Type_Region_Part := Part; when Region_Support.An_Incomplete_Type_Declaration | Region_Support.A_Private_Type_Declaration => To.Private_Or_Incomplete_Region_Part := Part; when Region_Support.A_Record_Representation_Clause => To.Record_Rep_Clause_Region_Part := Part; when others => null; end case; when Structures.A_Rename => case Region_Part_Kind is when Region_Support.A_Procedure_Rename_Declaration | Region_Support.A_Function_Rename_Declaration => To.Rename_Region_Part := Part; when others => null; end case; when Structures.A_Generic_Formal_Subprogram => case Region_Part_Kind is when Region_Support. A_Generic_Formal_Procedure_Specification | Region_Support. A_Generic_Formal_Function_Specification => To.Generic_Formal_Subprogram_Region_Part := Part; when others => null; end case; when Structures.A_Generic_Formal_Private_Type => case Region_Part_Kind is when Region_Support. A_Generic_Formal_Private_Type_Declaration => To.Generic_Formal_Private_Type_Region_Part := Part; when others => null; end case; when Structures.A_Block_Statement => case Region_Part_Kind is when Region_Support.A_Block_Statement => To.Block_Statement_Region_Part := Part; when others => null; end case; when Structures.A_Loop_Statement => case Region_Part_Kind is when Region_Support.A_For_Loop_Statement | Region_Support.A_While_Loop_Statement | Region_Support.A_Simple_Loop_Statement => To.Loop_Statement_Region_Part := Part; when others => null; end case; end case; end Add_Region_Part; ------------------------------------------------------------------------------- procedure Append (Item : in Structures.Region_Part_Ptr; As_Child_Of : in out Structures.Region_Part_Ptr) is New_Element : Structures.Region_Part_List; List : Structures.Region_Part_List; function "=" (Left, Right : Structures.Region_Part_List) return Boolean renames Structures."="; begin New_Element := new Structures.Region_Part_List_Element; New_Element.Region_Part := Item; if As_Child_Of.Children = null then As_Child_Of.Children := New_Element; else List := As_Child_Of.Children; loop exit when List.Next = null; List := List.Next; end loop; List.Next := New_Element; end if; end Append; ------------------------------------------------------------------------------- procedure Append (Item : in Structures.Declarative_Region_Ptr; As_Child_Of : in out Structures.Declarative_Region_Ptr) is New_Element : Structures.Declarative_Region_List; List : Structures.Declarative_Region_List; function "=" (Left, Right : Structures.Declarative_Region_List) return Boolean renames Structures."="; begin New_Element := new Structures.Declarative_Region_List_Element; New_Element.Declarative_Region := Item; if As_Child_Of.Children = null then As_Child_Of.Children := New_Element; else List := As_Child_Of.Children; loop exit when List.Next = null; List := List.Next; end loop; List.Next := New_Element; end if; end Append; end Region_View;