!standard 10.11 09-05-13 SI99-0046-1/03 !standard 10.12 !standard 10.13 !standard 10.14 !standard 15.13 !standard 15.26 !standard 15.27 !standard 15.40 !standard 15.42 !class binding interpretation !status ARG Approved 7-0-2 09-02-20 !status work item 09-02-16 !status received 09-02-16 !priority Medium !difficulty Easy !qualifier Omission !subject Clarify the Context parameter in ASIS queries !summary A number of ASIS queries are documented as pairs of queries, with one containing an Asis.Context parameter, and the other that works on the Enclosing_Context of its argument. The use of the Asis.Context parameter is not clearly documented. !question Should we clarify the intent of the Asis.Context parameter in these queries (Yes)? !recommendation Add wording clarifying the use of the library parameter in the queries Corresponding_Children, Corresponding_Parent_Declaration, Corresponding_Declaration, Corresponding_Body that operate on Asis.Compilation_Units, and in the queries Corresponding_Declaration, Corresponding_Body, Corresponding_Type_Declaration, Corresponding_Subunit, and Corresponding_Body_Stub that operate on Asis.Declarations. !wording In 10.11, (Corresponding_Children): Add the following paragraph just before "These two function calls will always produce identical results:" If The_Context specifies a context that is different from the Enclosing_Context(Library_Unit), returns a list of the child units for the parent library unit that Is_Equal to Library_Unit in The_Context. If no such parent library unit exists in The_Context, returns a Nil_Compilation_Unit_List. Delete (as this says the same thing as the next paragraph): Any non-Nil result will have an Enclosing_Context value that Is_Identical to The_Context. Modify: The Enclosing_Context for any non-Nil result will always be {Is_Identical to }The_Context, ... In 10.12, (Corresponding_Parent_Declaration): Add the following paragraph just before "These two function calls will always produce identical results:" If The_Context specifies a context that is different from the Enclosing_Context(Library_Unit), returns the parent library unit for the child unit in The_Context that Is_Equal to Library_Item. If no such child unit exists in The_Context, returns a Nil_Compilation_Unit. Delete (as this says the same thing as the next paragraph): Any non-Nil result will have an Enclosing_Context value that Is_Identical to The_Context. Modify: The Enclosing_Context for any non-Nil result will always be {Is_Identical to }The_Context, ... In 10.13, (Corresponding_Declaration (unit)): Add the following paragraph just before "Library_Item expects a unit of Unit_Kinds:" If The_Context specifies a context that is different from the Enclosing_Context(Library_Item), returns the corresponding library unit declaration for the library unit body in The_Context that Is_Equal to Library_Item. If no such library unit body exists in The_Context, returns a Nil_Compilation_Unit. Delete (as this says the same thing as the next paragraph): Any non-Nil result will have an Enclosing_Context value that Is_Identical to The_Context. Modify: The Enclosing_Context for any non-Nil result will always be {Is_Identical to }The_Context, ... In 10.14, (Corresponding_Body (unit)): Add the following paragraph just before "Library_Item expects a unit of Unit_Kinds:" If The_Context specifies a context that is different from the Enclosing_Context(Library_Item), returns the corresponding library unit body for the library unit in The_Context that Is_Equal to Library_Item. If no such library unit exists in The_Context, returns a Nil_Compilation_Unit. Delete (as this says the same thing as the next paragraph): Any non-Nil result will have an Enclosing_Context value that Is_Identical to The_Context. Modify: The Enclosing_Context for any non-Nil result will always be {Is_Identical to }The_Context, ... In 15.13, (Corresponding_Type_Declaration): Add the following paragraph just after the paragraph that begins with "The parameter The_Context ..." If The_Context specifies a context that is different from the Enclosing_Context(Enclosing_Compilation_Unit(Declaration)), returns the corresponding type declaration for the element in The_Context that Is_Equal to Declaration. If no such element exists in The_Context that Is_Equal to Declaration, returns A_Nil_Element. Delete the paragraph starting with "The parameter The_Context ..." In 15.26, (Corresponding_Declaration (declaration)): Add the following paragraph just after the paragraph that begins with "The parameter Context ...". If The_Context specifies a context that is different from the Enclosing_Context(Enclosing_Compilation_Unit(Declaration)), returns the declaration for the element in The_Context that Is_Equal to Declaration. If no such element exists in The_Context that Is_Equal to Declaration, returns A_Nil_Element. In 15.27, (Corresponding_Body (declaration)): Add the following paragraph just after the paragraph that begins with "The parameter Context ...". If The_Context specifies a context that is different from the Enclosing_Context(Enclosing_Compilation_Unit(Declaration)), returns the body for the element in The_Context that Is_Equal to Declaration. If no such element exists in The_Context that Is_Equal to Declaration, returns A_Nil_Element. In 15.40, (Corresponding_Subunit): Add the following just after the sentence beginning with "The parameter The_Context ...": If The_Context specifies a context that is different from the Enclosing_Context(Enclosing_Compilation_Unit(Body_Stub)), returns the unit declaration for the element in The_Context that Is_Equal to Body_Stub. If no such element exists in The_Context that Is_Equal to Body_Stub, returns A_Nil_Element. In 15.42, (Corresponding_Body_Stub): Add the following just after the sentence beginning with "The parameter The_Context ...": If The_Context specifies a context that is different from the Enclosing_Context(Enclosing_Compilation_Unit(Subunit)), returns the body stub for the element in The_Context that Is_Equal to Subunit. If no such element exists in The_Context that Is_Equal to Subunit, returns A_Nil_Element. !discussion We considered making queries that include a context parameter obsolescent. They are nearly useless, as Is_Equal is defined to return true for different contexts if the element comes from the same version (as defined in the Ada Standard) of the same compilation unit. But a unit U has the same version only if nothing at all has changed, including the units that U depends on. That means that multiple contexts can't be used to compare versions of units. For many popular compilers, it would be impossible for two contexts to have the same version of a unit (since they recompile everything each time it is used); it's hard to imagine what useful could be done in that case. However, we didn't make the queries obsolescent simply because we don't have an alternative to them. If someone does have a use for multiple contexts and their implementation supports them (that is not required), it would be silly to say that they shouldn't do it. So we ought to be conservative and leave these alone. !appendix ASIS 83 Issues #033 and #054 on the same topic: >!ASIS Issue #033 >!topic Corresponding_Declaration and Corresponding_Body >!reference ASIS 95-15.26 >!from Jesper Jorgensen 97-02-09 >!keywords Corresponding_Declaration Corresponding_Body >!discussion I miss to see the usefulness of being able to locate a declaration in another context. How should the body and declaration be related?. If there is a compilation unit body X in some context and a compilation unit specification X in some other context, they might be totally unrelated, just accidentally having the same name. If they are unrelated, how should ASIS be able to locate some inner unit? I think that only searching in the same context makes sense. What is the intended use of the other possibility? >!resolution Accepted, with Modifications. >!date >!Notes The following rationale for queries with an additional Context parameter appears in Annex D.4.8, titled "Queries with Additional Context Parameter". Several queries, including Corresponding_Declaration and Corresponding_Body, are overloaded with an additional parameter, Context. The additional queries are there for flexibility and power, should an ASIS implementation be able to take advantage of it. Some ASIS implementations may be able to support multiple open Contexts at the same time. Tools that would make use of more than one Context could be severely limited if they do not have the control provided by the Context parameter. An example of such a tool would be one that compared two contexts, identifying units appearing in both and ensuring their semantic dependent units were consistent, perhaps for some configuration management purpose. The Corresponding_Declaration in a different context should always be the declaration upon which the body depends semantically in that context, not just an unrelated declaration of the same name. ASIS implementations that only allow one open Context can implement these pairs of queries in tandem, with one simply calling the other and providing the current Context as a parameter. See also Issue #054. >!ASIS Issue #054 >!topic Queries having Context as additional parameter >!reference ASIS 95-10.15 >!from Sergey Rybin 97-03-03 >!keywords Context >!discussion ASIS contains a number of pairs of queries, in each of these pairs, both queries have the same name, they have similar functionality, the first query in the pair has one parameter, but the second one contains additional parameter of a Context type. There are two groups of these pairs - one contains queries from Asis.Compilation_Units, another contains semantic queries from Asis.Declarations working on Elements. Some time ago I sent to the ASIS forum the question about the semantic of Compilation unit queries having a Context as an additional parameter. We had a short discussion with Steve about these queries resulting with some kind of "semi-formalization" of the semantic of this additional parameter (Steve, correct me if I'm wrong, unfortunately I've failed to find the corresponding messages in my archive). For example, for the Corresponding_Parent_Declaration query (its definition is appended to this message), the semantic of the second "version" of the query may be expressed in Ada pseudo-code as: function Corresponding_Parent_Declaration (Library_Unit : in Asis.Compilation_Unit; The_Context : in Asis.Context) return Asis.Compilation_Unit is begin if Is_Identical (Enclosing_Context (Library_Unit), The_Context) then -- no difference with the "first version" of -- Corresponding_Parent_Declaration, therefore return Corresponding_Parent_Declaration (Library_Unit); else if (there exists a unit Library_Unit_1 in the context The_Context such that Is_Equal (Library_Unit_1, Library_Unit) then return Corresponding_Parent_Declaration (Library_Unit_1); else return Nil_Compilation_Unit; end if; end if; end Corresponding_Parent_Declaration; Now let's consider some example of a query working on Elements and having a Context as an additional parameter: ------------------------------------------------------------------------------ -- Section 15.13 function Corresponding_Type_Declaration ------------------------------------------------------------------------------ function Corresponding_Type_Declaration (Declaration : in Asis.Declaration) return Asis.Declaration; function Corresponding_Type_Declaration (Declaration : in Asis.Declaration; The_Context : in Asis.Context) return Asis.Declaration; ------------------------------------------------------------------------------ -- Declaration - Specifies the type declaration to query -- The_Context - Specifies the program Context to use for obtaining package -- body information -- -- Returns the corresponding full type declaration when given a private or -- incomplete type declaration. Returns the corresponding private or -- incomplete type declaration when given a full type declaration. -- -- These two function calls will always produce identical results: -- -- Decl2 := Corresponding_Type_Declaration( Decl1 ); -- Decl2 := Corresponding_Type_Declaration -- ( Decl1, -- Enclosing_Context( Enclosing_Compilation_Unit( Decl1 ))); -- -- Returns a Nil_Element when a full type declaration is given that has no -- corresponding private or incomplete type declaration, or when a -- corresponding type declaration does not exist within The_Context. -- -- The parameter The_Context is used whenever the corresponding full type of -- an incomplete type is in a corresponding package body. See RM 95 3.10.1(3). -- Any non-Nil result will always have the given Context as its -- Enclosing_Context. -- -- Appropriate Declaration_Kinds: -- An_Ordinary_Type_Declaration -- A_Task_Type_Declaration -- A_Protected_Type_Declaration -- An_Incomplete_Type_Declaration -- A_Private_Type_Declaration -- A_Private_Extension_Declaration -- -- Returns Declaration_Kinds: -- Not_A_Declaration -- An_Ordinary_Type_Declaration -- A_Task_Type_Declaration -- A_Protected_Type_Declaration -- An_Incomplete_Type_Declaration -- A_Private_Type_Declaration -- ------------------------------------------------------------------------------ First, I would say, that the definition of all the queries from Asis.Declarations, which have a Context as an additional parameter, is not very clear. Second, I would suggest the following interpretation of this query: function Corresponding_Type_Declaration (Declaration : in Asis.Declaration; The_Context : in Asis.Context) return Asis.Declaration is Arg_Enclosing_Context : Asis.Context := Enclosing_Context (Enclosing_Compilation_Unit (Declaration)); begin if Is_Identical (Arg_Enclosing_Context, The_Context) then -- no difference with the "first version" of -- Corresponding_Type_Declaration, therefore return Corresponding_Type_Declaration (Declaration); else if (there exists a unit Library_Unit_1 in the context The_Context such that Is_Equal (Library_Unit_1, Enclosing_Compilatin_Unit (Declaration)) and then (there exists an Element Declaration_1 in Library_Unit_1 such that Is_Equal (Declaration, Declaration_1) ) then return Corresponding_Type_Declaration (Declaration_1); else return Nil_Element; end if; end if; end Corresponding_Type_Declaration; And, the most important: if both these interpretations are correct (look reasonable), I would definitely say, that all the queries having a Context as an additional parameter are *SECONDARY QUERIES*, and as being secondary, they should be *MOVED* from the official ASIS definition into the corresponding ASIS secondary layer. I do not think, that something really important for applications would be lost, even if we would simply delete all these queries, but deleting these queries would definitely make ASIS more clear (and shorter, of course :-) >!resolution Accepted, with Modifications. >!date >!Notes The following rationale for queries with an additional Context parameter appears in Annex D.4.8, titled "Queries with an Additional Context Parameter". Several queries, including Corresponding_Declaration and Corresponding_Body, are overloaded with an additional parameter, Context. The additional queries are there for flexibility and power, if an ASIS implementation can take advantage of it. Some ASIS implementations may be able to support multiple open Contexts at the same time. Tools that would make use of more than one Context could be severely limited if they do not have the control provided by the Context parameter. An example of such a tool would be one that compared two contexts, identifying units appearing in both and ensuring their semantic dependent units were consistent, perhaps for some configuration management purpose. The Corresponding_Declaration in a different context should always be the declaration upon which the body depends semantically in that context, not just an unrelated declaration of the same name. ASIS implementations that only allow one open Context can implement these pairs of queries in tandem, with one simply calling the other and providing the current Context as a parameter. See also Issue #033. ****************************************************************