!standard B.2.1 10-01-26 SI99-0060-1/01 !class amendment 10-01-26 !status work item 10-01-26 !status received 09-06-08 !priority Medium !difficulty Easy !qualifier Omission !subject Add an example of a ASIS semantic subsystem !summary !question There is no example of using the ASIS semantic subsystem in the standard. Should there be one? (Yes.) !recommendation (See summary.) !wording B.2.1 An ASIS semantic subsystem application to build a call tree This example adds Dispatching_Call processing to the previous example, via the ASIS semantic subsystem. with Asis.Views; with Asis.Expressions.Views; with Asis.Callable_Views; with Asis.Subtype_Views; with Ada.Wide_Text_Io; use Ada.Wide_Text_Io; separate (Check_Compilation_Unit) procedure Process_Dispatching_Call (A_Call : in Asis.Element) is Call_Name : Asis.Name; begin if Asis.Statements.Is_Dispatching_Call(A_Call) then -- Get the element representing the name of the call case Asis.Elements.Element_Kind (A_Call) is when Asis.An_Expression => case Asis.Elements.Expression_Kind (A_Call) is when Asis.A_Function_Call => Call_Name := Asis.Expressions.Prefix(A_Call); when others => null; end case; when Asis.A_Statement => case Asis.Elements.Statement_Kind (A_Call) is when Asis.A_Procedure_Call_Statement => Call_Name:= Asis.Statements.Called_Name(A_Call); when others => null; end case; when others => null; end case; declare -- create the callable_view from the call_name Call_View : constant Asis.Callable_Views.Callable_View'Class := Asis.Callable_Views.Callable_View (Asis.Expressions.Views.Corresponding_View (Call_Name)); -- via a semantic query, determine the controlling type Controlling_Type : constant Asis.Subtype_Views.Subtype_View'Class := Asis.Callable_Views.Associated_Tagged_Type(Call_View); -- determine the declaration of the callee and the controlling type Callee_Decl : constant Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Call_View)); Type_Decl : constant Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Controlling_Type)); -- Output the dispatching call info begin Put ("Dispatching Call to "); Put ("Procedure "); Put ( Asis.Views.Declarative_Regions.Expanded_Name(Callee_Decl)); Put (" with controlling tagged type of "); Put_Line ( Asis.Views.Declarative_Regions.Expanded_Name(Type_Decl)); end; end if; end Process_Dispatching_Call; !discussion !appendix From: Bill Thomas Sent: Monday, June 8, 2009 11:45 PM Unfortunately due to a late breaking work conflict I am not able to attend the meeting in Brest. Part of my homework was to develop example programs illustrating the use of the new semantic queries to be included in the standard. Annex B currently has an example (B.2) that writes out call statements to build a call tree (e.g., "P (calls) Q"). For dispatching calls, nothing is output, due to inherent limitations of the queries Corresponding_Called_Function and Corresponding_Called_Entity. I suggest that we extend this example to output similar dispatching call information making use of the new semantic queries. The example would use the semantic interface to: - navigate from an element to a view - navigate from a view to a view_declaration - output the name of an entity The code is below. It should be called with the parameter being an expression representing a dispatching function call or a statement representing a dispatching procedure call. I would appreciate any comments on this. Some questions are: 1) Does this look like a reasonable use of the semantic interface? 2) Am I making an appropriate use of "Asis.Views.Declaration" to determine the name (via the view_declaration) of the called entity? Is this reasonable for a dispatching call? 3) I did not see a way to navigate from an Asis.Statement to a Callable_View. I added the "Asis.Statments.Corresponding_View" query to support this (note the comment in J.P.'s review). Is this reasonable? 4) Is there anything else that should be added to this example? -------------------------------------------------- with Asis.Views; with Asis.Expressions.Views; with Asis.Statements.Views; with Asis.Callable_Views; with Asis.Subtype_Views; with Ada.Wide_Text_Io; use Ada.Wide_Text_Io; separate (Check_Compilation_Unit) procedure Process_Dispatching_Call (A_Call : in Asis.Element) is begin if Asis.Statements.Is_Dispatching_Call (A_Call) then case Asis.Elements.Element_Kind (A_Call) is when Asis.An_Expression => case Asis.Elements.Expression_Kind (A_Call) is when Asis.A_Function_Call => if Asis.Views.Has_Declaration (Asis.Expressions.Views.Corresponding_View(A_Call)) then declare -- get the view of the call Call_View : Asis.Callable_Views.Callable_View'Class := Asis.Callable_Views.Callable_View (Asis.Expressions.Views.Corresponding_View(A_Call)); -- get the controlling tagged type Controlling_Type : Asis.Subtype_Views.Subtype_View'Class := Asis.Callable_Views.Associated_Tagged_Type (Call_View); -- get the target of the call Callee_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Call_View)); -- get the declaration of the controlling tagged type Type_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Controlling_Type)); -- Output the dispatching call info begin Put ("Dispatching Call to "); Put ( Asis.Views.Declarative_Regions.Expanded_Name(Callee_Decl)); Put (" with controlling type "); Put_Line ( Asis.Views.Declarative_Regions.Expanded_Name(Type_Decl)); end; end if; when others => null; end case; when Asis.A_Statement => case Asis.Elements.Statement_Kind (A_Call) is when Asis.A_Procedure_Call_Statement => if Asis.Views.Has_Declaration(Asis.Statements.Views.Corresponding_View(A_Call)) then declare Call_View : Asis.Callable_Views.Callable_View'Class := Asis.Callable_Views.Callable_View (Asis.Statements.Views.Corresponding_View(A_Call)); Controlling_Type : Asis.Subtype_Views.Subtype_View'Class := Asis.Callable_Views.Associated_Tagged_Type(Call_View); Callee_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Call_View)); Type_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Controlling_Type)); begin Put ("Dispatching Call to "); Put ( Asis.Views.Declarative_Regions.Expanded_Name(Callee_Decl)); Put (" with controlling type "); Put_Line ( Asis.Views.Declarative_Regions.Expanded_Name(Type_Decl)); end; end if; when others => null; end case; when others => null; end case; end if; end Process_Dispatching_Call; **************************************************************** From: Tucker Taft Sent: Tuesday, June 9, 2009 1:53 AM I would think that most if not all of the local objects in your example could be declared as constants, rather than variables. Otherwise, looks like a helpful example. **************************************************************** From: Bill Thomas Sent: Monday, November 9, 2009 12:17 PM My new suggestion for the procedure (to print the name and controlling tagged type For a dispatching call) is below. Basically, Get the element representing the name for the call (for function calls, via Asis.Expressions.Prefix, and for procedure calls, via Asis.Statements.Called_Name) From that name, build a callable view (via Asis.Expressions.Views.Corresponding_View) Get the controlling type (via Asis.Callable_Views.Associated_Tagged_Type) Get the view declarations of the call name and controlling type (via Asis.Views.Declaration) Print the names (via Asis.Views.Declarative_Regions.Expanded_Name) Does this sound right? -- v2 of this procedure with Asis.Views; with Asis.Expressions.Views; with Asis.Callable_Views; with Asis.Subtype_Views; with Ada.Wide_Text_Io; use Ada.Wide_Text_Io; separate (Check_Compilation_Unit) procedure Process_Dispatching_Call (A_Call : in Asis.Element) is Call_Name : Asis.Name; begin if Asis.Statements.Is_Dispatching_Call(A_Call) then -- Get the element representing the name of the call case Asis.Elements.Element_Kind (A_Call) is when Asis.An_Expression => case Asis.Elements.Expression_Kind (A_Call) is when Asis.A_Function_Call => Call_Name := Asis.Expressions.Prefix(A_Call); when others => null; end case; when Asis.A_Statement => case Asis.Elements.Statement_Kind (A_Call) is when Asis.A_Procedure_Call_Statement => Call_Name:= Asis.Statements.Called_Name(A_Call); when others => null; end case; when others => null; end case; -- do we need to check if Asis.Views.Has_Declaration for the views declare -- create the callable_view from the call_name Call_View : Asis.Callable_Views.Callable_View'Class := Asis.Callable_Views.Callable_View (Asis.Expressions.Views.Corresponding_View (Call_Name)); -- via a semantic query, determine the controlling type Controlling_Type : Asis.Subtype_Views.Subtype_View'Class := Asis.Callable_Views.Associated_Tagged_Type(Call_View); -- determine the declaration of the callee and the controlling type Callee_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Call_View)); Type_Decl : Asis.Views.Declarative_Regions.View_Declaration'Class := Asis.Views.Declaration(Asis.Views.View'Class(Controlling_Type)); -- Output the dispatching call info begin Put ("Dispatching Call to "); Put ("Procedure "); Put ( Asis.Views.Declarative_Regions.Expanded_Name(Callee_Decl)); --WMT Put (" with controlling tagged type of "); Put_Line ( Asis.Views.Declarative_Regions.Expanded_Name(Type_Decl)); --WMT end; end if; end Process_Dispatching_Call; ****************************************************************