---------------------------------------------- ---------------------------------- -- -- -- OCARINA COMPONENTS -- -- -- -- O C A R I N A . A N A L Y Z E R -- -- -- -- 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 Ocarina.Nodes; with Ocarina.Nutils; with Ocarina.Entities; with Ocarina.Analyzer.Legality_Rules; with Ocarina.Analyzer.Names; with Ocarina.Analyzer.Links; with Ocarina.Analyzer.Semantics; with Ocarina.Analyzer.Naming_Rules; package body Ocarina.Analyzer is use Ocarina.Nodes; use Ocarina.Nutils; use Ocarina.Entities; use Ocarina.Analyzer.Legality_Rules; use Ocarina.Analyzer.Names; use Ocarina.Analyzer.Links; use Ocarina.Analyzer.Semantics; use Ocarina.Analyzer.Naming_Rules; function Same_Mode_Identifiers (Mode_Identifier_1 : node_id; Mode_Identifier_2 : node_id) return Boolean; -- Return True if the given identifiers represent the same mode ------------------ -- Analyze_Tree -- ------------------ function Analyze_Tree (Root : node_id; Options : analyzer_options) return Boolean is pragma assert (Kind (Root) = k_aadl_specification); Success : Boolean := True; begin Ocarina.Analyzer.Naming_Rules.Initialize; -- Check legality rules (properties, types...) Success := Check_Legality_Rules (Root, Options); -- Link the identifiers and designators to their -- corresponding AADL components and namespaces. Success := Success and then Check_Names_In_Namespaces (Root) and then Link_Declarations_Of_Namespaces (Root, Options); -- Check the semantics of the AADL specification in order -- to display the maximum amount of error messages. Success := Success and then Check_Semantics_In_Namespaces (Root); -- Link the identifiers and designators to their -- corresponding AADL subcomponents, subclauses or port -- groups. Success := Success and then Check_Names_In_Components_And_Port_Groups (Root) and then Link_Subclauses_In_Components_And_Port_Groups (Root, Options); -- Check the semantics of subclauses and port groups Success := Success and then Check_Semantics_In_Components (Root); -- Link the identifiers and designators to their -- corresponding AADL property types and constants and -- check the semantics of the properties. Success := Success and then Link_Property_Associations_Of_AADL_Description (Root, Options) and then Check_Semantics_Of_Properties (Root); return Success; end Analyze_Tree; --------------------------- -- Same_Mode_Identifiers -- --------------------------- function Same_Mode_Identifiers (Mode_Identifier_1 : node_id; Mode_Identifier_2 : node_id) return Boolean is pragma assert (Kind (Mode_Identifier_1) = k_entity_reference or else Kind (Mode_Identifier_1) = k_pair_of_entity_references); pragma assert (Kind (Mode_Identifier_2) = k_entity_reference or else Kind (Mode_Identifier_2) = k_pair_of_entity_references); Name_Id_1 : name_id; Name_Id_2 : name_id; begin if Kind (Mode_Identifier_1) /= Kind (Mode_Identifier_2) then return False; end if; if Kind (Mode_Identifier_1) = k_entity_reference then Name_Id_1 := Get_Name_Of_Entity_Reference (Mode_Identifier_1); Name_Id_2 := Get_Name_Of_Entity_Reference (Mode_Identifier_2); if Name_Id_1 = Name_Id_2 then return True; end if; elsif Kind (Mode_Identifier_1) = k_pair_of_entity_references then Name_Id_1 := Get_Name_Of_Entity_Reference (First_Reference (Mode_Identifier_1)); Name_Id_2 := Get_Name_Of_Entity_Reference (Second_Reference (Mode_Identifier_2)); if Name_Id_1 = Name_Id_2 then if No (Second_Reference (Mode_Identifier_1)) and then No (Second_Reference (Mode_Identifier_2)) then return True; else if Present (Second_Reference (Mode_Identifier_1)) then Name_Id_1 := Get_Name_Of_Entity_Reference (Second_Reference (Mode_Identifier_1)); else Name_Id_1 := No_Name; end if; if Present (Second_Reference (Mode_Identifier_2)) then Name_Id_2 := Get_Name_Of_Entity_Reference (Second_Reference (Mode_Identifier_2)); else Name_Id_2 := No_Name; end if; if Name_Id_1 = Name_Id_2 then return True; end if; end if; end if; end if; return False; end Same_Mode_Identifiers; -------------------------- -- Have_Modes_In_Common -- -------------------------- function Have_Modes_In_Common (Declaration1 : node_id; Declaration2 : node_id) return Boolean is pragma assert (Present (Declaration1) and then Present (Declaration2)); function Can_Have_Modes (Declaration : node_id) return Boolean; -- Return True if the given declaration can have modes -- according to the AADL standard. function Can_Have_Modes (Declaration : node_id) return Boolean is begin case Kind (Declaration) is when k_subcomponent | k_flow_implementation | k_end_to_end_flow_spec | k_flow_implementation_refinement | k_end_to_end_flow_refinement | k_connection | k_property_association | k_subprogram_call_sequence | k_subprogram_call => return True; -- Subprogram_Call receive the modes of their call -- sequence. This is set by the analyzer when others => return False; end case; end Can_Have_Modes; Can_Have_Modes_1 : constant Boolean := Can_Have_Modes (Declaration1); Can_Have_Modes_2 : constant Boolean := Can_Have_Modes (Declaration2); List_Mode_1 : node_id; List_Mode_2 : node_id; begin if Can_Have_Modes_1 and then Can_Have_Modes_2 then if not Have_Modes (In_Modes (Declaration1)) or else not Have_Modes (In_Modes (Declaration2)) then return True; -- If one of the two declaration does not have an 'in -- modes' statement, then it is declared for all existing -- modes. Hence it has modes in common with the other -- declaration. else List_Mode_1 := First_Node (Modes (In_Modes (Declaration1))); List_Mode_2 := First_Node (Modes (In_Modes (Declaration2))); while Present (List_Mode_1) loop while Present (List_Mode_2) loop if Same_Mode_Identifiers (List_Mode_1, List_Mode_2) then return True; end if; List_Mode_2 := Next_Node (List_Mode_2); end loop; List_Mode_1 := Next_Node (List_Mode_1); end loop; return False; end if; else return True; -- If none of the declarations can have modes, then they are -- to be present together. Hence it is the same situation as -- if they were declared in the same modes. end if; end Have_Modes_In_Common; --------------------- -- Is_A_Refinement -- --------------------- function Is_A_Refinement (Node : node_id) return Boolean is pragma assert (Present (Node)); begin case Kind (Node) is when k_subcomponent | k_flow_spec | k_port_spec | k_port_group_spec | k_subprogram_spec | k_parameter | k_subcomponent_access | k_mode | k_mode_transition | k_connection => return Is_Refinement (Node); when k_flow_implementation | k_end_to_end_flow_spec => return False; when k_flow_implementation_refinement | k_end_to_end_flow_refinement => return True; when others => return False; end case; end Is_A_Refinement; ---------------------------------- -- Append_Entity_To_Entity_List -- ---------------------------------- procedure Append_Entity_To_Entity_List (Entity : node_id; List : in out entity_list) is pragma assert (Present (Entity)); List_Node : node_id; begin if List.First_Entity = No_Node then List.First_Entity := Entity; List.Last_Entity := Entity; Set_Next_Entity (Entity, No_Node); else List_Node := List.First_Entity; while List_Node /= No_Node loop if List_Node = Entity then -- We stop here if the node is already in the list return; end if; List_Node := Next_Entity (List_Node); end loop; Set_Next_Entity (List.Last_Entity, Entity); List.Last_Entity := Entity; Set_Next_Entity (Entity, No_Node); end if; end Append_Entity_To_Entity_List; ----------------------- -- Clear_Entity_List -- ----------------------- procedure Clear_Entity_List (List : in out entity_list) is List_Node : node_id; P_List_Node : node_id; begin if List /= Empty_Entity_List then List_Node := List.First_Entity; while List_Node /= No_Node loop P_List_Node := List_Node; List_Node := Next_Entity (List_Node); Set_Next_Entity (P_List_Node, No_Node); end loop; List.First_Entity := No_Node; List.Last_Entity := No_Node; end if; end Clear_Entity_List; end Ocarina.Analyzer;