--------------------------------- ----------------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- OCARINA.EXPANDER.COMPONENTS.SUBPROGRAM_CALLS -- -- -- -- B o d y -- -- -- -- Copyright (C) 2005-2007, GET-Telecom Paris. -- -- -- -- Ocarina 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 2, or (at your option) any -- -- later version. Ocarina 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 Ocarina; see file COPYING. -- -- If not, write to the Free Software Foundation, 51 Franklin Street, Fifth -- -- Floor, Boston, MA 02111-1301, USA. -- -- -- -- As a special exception, if other files instantiate generics from this -- -- unit, or you link this unit with other files to produce an executable, -- -- this unit does not by itself cause the resulting executable to be -- -- covered by the GNU General Public License. This exception does not -- -- however invalidate any other reasons why the executable file might be -- -- covered by the GNU Public License. -- -- -- -- Ocarina is maintained by the Ocarina team -- -- (ocarina-users@listes.enst.fr) -- -- -- ------------------------------------------------------------------------------ with Locations; with Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.Annotations; with Ocarina.Expander.Messages; with Ocarina.Expander.Components; with Ocarina.Expander.Namespaces; with Ocarina.Entities.Components; package body Ocarina.Expander.Components.Subprogram_Calls is use Ocarina.Nodes; use Ocarina.Nutils; use Ocarina.Annotations; use Ocarina.Expander.Messages; use Ocarina.Expander.Components; use Ocarina.Expander.Namespaces; use Ocarina.Entities; use Ocarina.Entities.Components; -------------------------- -- Expand_Call_Sequence -- -------------------------- function Expand_Call_Sequence (Instance_Root : node_id; Call_Sequence : node_id) return node_id is pragma assert (Kind (Instance_Root) = k_architecture_instance); pragma assert (Kind (Call_Sequence) = k_subprogram_call_sequence); New_Instance : constant node_id := New_Node (k_call_sequence_instance, Loc (Call_Sequence)); New_Subinstance : node_id; List_Node : node_id; Success : Boolean := True; begin Set_Identifier (New_Instance, Duplicate_Identifier (Identifier (Call_Sequence))); Set_Corresponding_Declaration (New_Instance, Call_Sequence); if Ocarina.Nodes.Subprogram_Calls (Call_Sequence) /= No_List then Set_Subprogram_Calls (New_Instance, New_List (k_list_id, Loc (node_id (Ocarina.Nodes.Subprogram_Calls (Call_Sequence))))); List_Node := First_Node (Ocarina.Nodes.Subprogram_Calls (Call_Sequence)); while Present (List_Node) loop New_Subinstance := Expand_Subprogram_Call (Instance_Root, List_Node); if Present (New_Subinstance) then Set_Parent_Sequence (New_Subinstance, New_Instance); Append_Node_To_List (New_Subinstance, Ocarina.Nodes.Subprogram_Calls (New_Instance)); else Success := False; end if; List_Node := Next_Node (List_Node); end loop; end if; if Success then return New_Instance; else return No_Node; end if; end Expand_Call_Sequence; ---------------------------- -- Expand_Subprogram_Call -- ---------------------------- function Expand_Subprogram_Call (Instance_Root : node_id; Subprogram_Call : node_id) return node_id is pragma assert (Kind (Instance_Root) = k_architecture_instance); pragma assert (Kind (Subprogram_Call) = k_subprogram_call); New_Instance : constant node_id := New_Node (k_call_instance, Loc (Subprogram_Call)); Container : constant node_id := Container_Component (Parent_Sequence (Subprogram_Call)); New_Subinstance : node_id := No_Node; Namespace_Instance : node_id := No_Node; Namespace_Model : node_id; Owner_Data : node_id; begin Set_Identifier (New_Instance, Duplicate_Identifier (Identifier (Subprogram_Call))); Set_Corresponding_Declaration (New_Instance, Subprogram_Call); if Present (Entity_Ref (Subprogram_Call)) and then Present (Get_Referenced_Entity (Entity_Ref (Subprogram_Call))) then -- Getting the component namespace Namespace_Model := Namespace (Get_Referenced_Entity (Entity_Ref (Subprogram_Call))); Namespace_Instance := Expand_Namespace (Instance_Root, Namespace_Model); -- If this is a method call, get the owner data component if Length (Path (Entity_Ref (Subprogram_Call))) > 1 then Owner_Data := Corresponding_Entity (Item (First_Node (Path (Entity_Ref (Subprogram_Call))))); -- If we deal with a call to a subprogram -- implementation, the length of the path is 2 but the -- first identifier does not reference anything. Thus, -- Owner_Data is nul for subprogram implmentation calls. if Present (Owner_Data) and then (Kind (Owner_Data) = k_component_type or else Kind (Owner_Data) = k_component_implementation) and then Get_Category_Of_Component (Owner_Data) = cc_data then declare D : node_id; F : node_id; begin Set_Path (New_Instance, New_List (k_list_id, Locations.No_Location)); D := Expand_Component (Instance_Root, Owner_Data); -- Append the data that owns the method Append_Node_To_List (Make_Node_Container (D), Path (New_Instance)); -- Append the feature that correspods to the call F := First_Node (Features (D)); while Present (F) loop if Kind (F) = k_subprogram_spec_instance and then Corresponding_Declaration (F) = Entity (Entity_Ref (Subprogram_Call)) then Append_Node_To_List (Make_Node_Container (F), Path (New_Instance)); end if; F := Next_Node (F); end loop; -- If no feature matched, there is a serious problem if Length (Path (New_Instance)) < 2 then raise Program_Error with "Owner data without features"; end if; -- Annotate the data component with parent component -- of the subprogram call Annotate (Owner_Data, Container); end; end if; end if; -- Each subprogram call expansion leads to the creation of a -- new subprogram component instance. declare Spg_Component : constant node_id := Get_Referenced_Entity (Entity_Ref (Subprogram_Call)); begin New_Subinstance := Expand_Component (Instance_Root, Spg_Component); if Present (New_Subinstance) then Set_Corresponding_Instance (New_Instance, New_Subinstance); Set_Parent_Subcomponent (New_Subinstance, New_Instance); -- The namespace declaration list is a node container -- list because we cannot append the same node in two -- different lists. Append_Node_To_List (Make_Node_Container (New_Subinstance), Declarations (Namespace_Instance)); -- Annotate the subprogram component with container -- component of the subprogram call. Annotate (Spg_Component, Container); return New_Instance; else return No_Node; end if; end; else Display_No_Entity_Ref (New_Instance); return No_Node; end if; end Expand_Subprogram_Call; ---------------------------------------- -- Duplicate_Subprogram_Call_Instance -- ---------------------------------------- function Duplicate_Subprogram_Call_Instance (Instance_Root : node_id; Call_Instance : node_id) return node_id is pragma assert (Kind (Call_Instance) = k_call_instance); New_Subinstance : node_id; begin if Default_Instance (Corresponding_Declaration (Corresponding_Instance (Call_Instance))) = Corresponding_Instance (Call_Instance) then -- We only create a new instance of the subprogram if the -- current instance is the default one. New_Subinstance := Expand_Component (Instance_Root, Corresponding_Declaration (Corresponding_Instance (Call_Instance))); if Present (New_Subinstance) then Set_Corresponding_Instance (Call_Instance, New_Subinstance); return Call_Instance; else return No_Node; end if; else return Call_Instance; end if; end Duplicate_Subprogram_Call_Instance; end Ocarina.Expander.Components.Subprogram_Calls;