------------------------------ -------------------------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- O C A R I N A . E X P A N D E R . C O M P O N E N T S -- -- -- -- 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.Components.Subcomponents; with Ocarina.Expander.Components.Subprogram_Calls; with Ocarina.Expander.Components.Features; with Ocarina.Expander.Components.Connections; with Ocarina.Expander.Components.Modes; with Ocarina.Expander.Namespaces; with Ocarina.Expander.Properties; with Ocarina.Expander.Messages; with Ocarina.Entities.Components; package body Ocarina.Expander.Components is use Locations; use Ocarina.Nodes; use Ocarina.Nutils; use Ocarina.Annotations; use Ocarina.Expander.Components.Subcomponents; use Ocarina.Expander.Components.Subprogram_Calls; use Ocarina.Expander.Components.Features; use Ocarina.Expander.Components.Connections; use Ocarina.Expander.Components.Modes; use Ocarina.Expander.Namespaces; use Ocarina.Expander.Properties; use Ocarina.Expander.Messages; use Ocarina.Entities; use Ocarina.Entities.Components; procedure Add_Component_Instance (Component : Node_Id; Instance : Node_Id); -- Reference a component instance that has been expanded from -- Component. ---------------------------- -- Add_Component_Instance -- ---------------------------- procedure Add_Component_Instance (Component : Node_Id; Instance : Node_Id) is pragma Assert (Kind (Component) = K_Component_Implementation or else Kind (Component) = K_Component_Type); pragma Assert (Kind (Instance) = K_Component_Instance); begin if Is_Empty (Instances (Component)) then Set_Instances (Component, New_List (K_List_Id, Loc (Component))); end if; Append_Node_To_List (Instance, Instances (Component)); end Add_Component_Instance; ---------------------- -- Expand_Component -- ---------------------- function Expand_Component (Instance_Root : Node_Id; Component : Node_Id; Existing_Instance : Node_Id := No_Node) return Node_Id is pragma Assert (Kind (Instance_Root) = K_Architecture_Instance); pragma Assert (Kind (Component) = K_Component_Implementation or else Kind (Component) = K_Component_Type); New_Instance : Node_Id := Existing_Instance; List_Node : Node_Id; Instance_Node : Node_Id; Success : Boolean := True; Namespace_Instance : Node_Id; begin -- Data components have to be expanded only once. Other -- components may be expanded more than once. This avoids -- infinite recursion in the case subprograms are features of -- data and require/provide access to the same data. However, -- if different data components inherit from the same parent -- data component, the later has to be expanded for each -- child. This case is known if the Existing_Instance parameter -- is not nul. if different data component are implementations -- of the same component type, the later has to be expanded for -- each implementation. if No (Existing_Instance) and then Component_Category'Val (Category (Component)) = CC_Data and then Present (Get_Expansion (Component)) then return Get_Expansion (Component); end if; -- Getting the component namespace Namespace_Instance := Expand_Namespace (Instance_Root, Namespace (Component)); -- Annotate the component with itself Annotate (Component, Component); if No (New_Instance) then New_Instance := New_Node (K_Component_Instance, Loc (Component)); Add_Component_Instance (Component, New_Instance); Set_Corresponding_Declaration (New_Instance, Component); Set_Identifier (New_Instance, Duplicate_Identifier (Identifier (Component))); Set_Corresponding_Entity (Identifier (New_Instance), New_Instance); Set_Namespace (New_Instance, Namespace_Instance); end if; -- Mark the component as being expanded. It is important that -- we mark the component as expanded before computing its -- subcomponent to avoid endless recursion. We mark only if -- this is the top level component during expansion -- (Existing_Instance is nul). if No (Existing_Instance) then Set_Expansion (Component, New_Instance); end if; if No (Existing_Instance) and then Kind (Component) = K_Component_Implementation then -- If we are dealing with a component implementation, then -- we have to compute the corresponding component type. declare Component_Type : constant Node_Id := Corresponding_Entity (Component_Type_Identifier (Component)); begin -- Annotate the component type node with the -- component implementation node. Annotate (Component_Type, Component); -- Expand the component type New_Instance := Expand_Component (Instance_Root, Component_Type, New_Instance); end; end if; -- Recursively expand the parent components implementations and -- types. if Present (Parent (Component)) then declare The_Parent : constant Node_Id := Get_Referenced_Entity (Parent (Component)); begin -- Annotate the parent component with the current -- component. Annotate (The_Parent, Component); -- Expand the parent component New_Instance := Expand_Component (Instance_Root, The_Parent, New_Instance); end; end if; -- If there was a problem during the expansion, we immediately -- exit. This case should normally not happen, though. if No (New_Instance) then Display_Expansion_Error (Component); return No_Node; end if; -- Then expand the component itself if Kind (Component) = K_Component_Implementation then -- If we are dealing with a component implementation -- Subcomponents if not Is_Empty (Ocarina.Nodes.Subcomponents (Component)) then if Ocarina.Nodes.Subcomponents (New_Instance) = No_List then Set_Subcomponents (New_Instance, New_List (K_List_Id, No_Location)); end if; List_Node := First_Node (Ocarina.Nodes.Subcomponents (Component)); while Present (List_Node) loop if No (Get_First_Homonym (Ocarina.Nodes.Subcomponents (New_Instance), List_Node)) then -- We do not re-expand subcomponent refinements Instance_Node := Expand_Subcomponent (Instance_Root, List_Node); if Present (Instance_Node) then -- Annotate the corresponding component of the -- subcomponent with the current AADL component -- implementation. Annotate (Get_Referenced_Entity (Entity_Ref (List_Node)), Component); -- Set the component instance and the -- subcomponent instance. Set_Parent_Component (Instance_Node, New_Instance); Append_Node_To_List (Instance_Node, Ocarina.Nodes.Subcomponents (New_Instance)); -- We apply the properties to the component -- corresponding to the subcomponent. Success := Apply_Properties (Instance_Root, Corresponding_Instance (Instance_Node), Ocarina.Nodes.Properties (List_Node)) and then Success; else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; -- Subprogram call sequences if not Is_Empty (Calls (Component)) then if Calls (New_Instance) = No_List then Set_Calls (New_Instance, New_List (K_List_Id, No_Location)); end if; List_Node := First_Node (Calls (Component)); while Present (List_Node) loop if Get_First_Homonym (Calls (New_Instance), List_Node) = No_Node then Instance_Node := Expand_Call_Sequence (Instance_Root, List_Node); if Present (Instance_Node) then Set_Parent_Component (Instance_Node, New_Instance); Append_Node_To_List (Instance_Node, Calls (New_Instance)); else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; -- Refined features if Refines_Type (Component) /= No_List then if Ocarina.Nodes.Features (New_Instance) = No_List then Set_Features (New_Instance, New_List (K_List_Id, No_Location)); end if; List_Node := First_Node (Ocarina.Nodes.Refines_Type (Component)); while Present (List_Node) loop if No (Get_First_Homonym (Ocarina.Nodes.Features (New_Instance), List_Node)) then Instance_Node := Expand_Feature (Instance_Root, List_Node); if Present (Instance_Node) then Success := Apply_Properties (Instance_Root, Instance_Node, Ocarina.Nodes.Properties (List_Node)) and then Success; Append_Node_To_List (Instance_Node, Ocarina.Nodes.Features (New_Instance)); else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; -- Connections if not Is_Empty (Ocarina.Nodes.Connections (Component)) then if Ocarina.Nodes.Connections (New_Instance) = No_List then Set_Connections (New_Instance, New_List (K_List_Id, No_Location)); end if; List_Node := First_Node (Ocarina.Nodes.Connections (Component)); while Present (List_Node) loop if No (Get_First_Homonym (Ocarina.Nodes.Connections (New_Instance), List_Node)) then Instance_Node := Expand_Connection (Instance_Root, New_Instance, List_Node); if Present (Instance_Node) then Append_Node_To_List (Instance_Node, Ocarina.Nodes.Connections (New_Instance)); else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; -- Modes if not Is_Empty (Ocarina.Nodes.Modes (Component)) then if Ocarina.Nodes.Modes (New_Instance) = No_List then Set_Modes (New_Instance, New_List (K_List_Id, No_Location)); end if; if Ocarina.Nodes.Mode_transitions (New_Instance) = No_List then Set_Mode_transitions (New_Instance, New_List (K_List_Id, No_Location)); end if; -- We must instantiate all modes before any mode -- transition since the mode transition instantiation -- uses the instantiated modes. List_Node := First_Node (Ocarina.Nodes.Modes (Component)); while Present (List_Node) loop if Kind (List_Node) = K_Mode then Instance_Node := Expand_Mode (Instance_Root, New_Instance, List_Node); -- Apply the properties to the instantiated mode if Present (Instance_Node) then Success := Apply_Properties (Instance_Root, Instance_Node, Ocarina.Nodes.Properties (List_Node)) and then Success; end if; if Present (Instance_Node) then Append_Node_To_List (Instance_Node, Ocarina.Nodes.Modes (New_Instance)); else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; -- Mode transitions List_Node := First_Node (Ocarina.Nodes.Modes (Component)); while Present (List_Node) loop if Kind (List_Node) = K_Mode_Transition then Instance_Node := Expand_Mode_Transition (Instance_Root, New_Instance, List_Node); if Present (Instance_Node) then Append_Node_To_List (Instance_Node, Ocarina.Nodes.Mode_transitions (New_Instance)); else Display_Expansion_Error (Component); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; -- At this point, we have all necessary elements to solve -- the "in_modes" clauses of subcomponents, call sequences, -- connections. "in modes" of property association is done -- when expanding the properties becaus it is a little bit -- more delicate. Expand_In_Modes (New_Instance, Ocarina.Nodes.Subcomponents (New_Instance)); Expand_In_Modes (New_Instance, Calls (New_Instance)); Expand_In_Modes (New_Instance, Ocarina.Nodes.Connections (New_Instance)); else -- This is a component type if Ocarina.Nodes.Features (Component) /= No_List then if Ocarina.Nodes.Features (New_Instance) = No_List then Set_Features (New_Instance, New_List (K_List_Id, No_Location)); end if; List_Node := First_Node (Ocarina.Nodes.Features (Component)); while Present (List_Node) loop if No (Get_First_Homonym (Ocarina.Nodes.Features (New_Instance), List_Node)) then Instance_Node := Expand_Feature (Instance_Root, List_Node); if Present (Instance_Node) then Success := Apply_Properties (Instance_Root, Instance_Node, Ocarina.Nodes.Properties (List_Node)) and then Success; Append_Node_To_List (Instance_Node, Ocarina.Nodes.Features (New_Instance)); Set_Parent_Component (Instance_Node, New_Instance); else Display_Expansion_Error (List_Node); Success := False; end if; end if; List_Node := Next_Node (List_Node); end loop; end if; end if; -- Property associations of the component instance Success := Apply_Properties (Instance_Root, New_Instance, Ocarina.Nodes.Properties (Component)) and then Success; if not Success then Display_Expansion_Error (Component); New_Instance := No_Node; elsif No (Default_Instance (Component)) then Set_Default_Instance (Component, New_Instance); end if; return New_Instance; end Expand_Component; end Ocarina.Expander.Components;