!standard 3.9 07-10-03 SI99-0024-1/06 !class amendment 06-11-12 !status work item 06-11-12 !status received 06-11-12 !priority High !difficulty Hard !subject Provide a semantic model in addition to existing syntactic model !summary ASIS currently provides a model that is closely based on the syntax. This SI proposes to add a set of packages that provide a canonicalized semantic model, which captures more of the work already done by (the front end of) the compiler. !problem The current ASIS model is very tied to the syntactic structure of the program library. However, there are times when it is more efficient to use a more abstract, semantic model. This SI proposes such a model. In one sense, it may be thought of as defining a "symbol table" for the program library. !proposal SEMANTIC VS. STRUCTURAL MODEL This SI proposes that an additional set of packages be provided as part of ASIS that represent a semantic model of the program library. As currently defined, ASIS provides a structural model of the library, with a relatively limited set of semantic queries that allow references to be traversed to their definitions, and allow traversal between declarations and bodies, or partial and full declarations. The existing approach provides all the information inherent in the original source program, and as such, ensures that other tools can do all the same work that the compiler could do. However, the existing approach doesn't capture much of that work in a useful form, and instead essentially requires that it be performed by every tool. In this SI we propose to capture more of the work already performed by the compiler, and along the way attempt to canonicalize the information so that the many special cases inherent in the syntactic structure of the program library are reduced to a smaller number of semantic concepts that nevertheless still cover the entire realm of possibilities. One way to think about what we are doing is providing a "symbol table" for the program library. GUIDES TO CREATING SEMANTIC MODEL To guide our efforts, we need to decide on what level of information we want to capture. In particular, there is the information that is implementation independent, and simply captures the language-defined static semantic properties of the program. This we might call the "language-level" semantic information. At the next level down, there is information that reflects some of the decisions made by the implementation which might be useful to a tool, such as the layout of a record, or the linkname of a global object. This we might call the "representation-level" information. Finally, as we get to the "object-code level," there is the information about the range of code addresses associated with each line of source, and the layout of the stack frame for particular subprograms. For this initial effort, we propose to focus on the "language-level" implementation-independent semantic properties. We envisage that additional packages might be defined as some later point, or by particular ASIS implementations, that provide the lower level "representation" or "object-code" information. The second guide to our efforts is a list of the typical kinds of applications we imagine being built using this high-level semantic model. One kind of application would be an interpreter, both an interpreter of existing code, and an interpreter of simple expressions or statements typed into the program interactively after establishing a particular context. For example, one might invoke a tool that would essentially elaborate some part of the program library, and then allow the user to type in small test scripts in an Ada-like language which would be interpreted in the context of the given part of the library, as a kind of interactive unit testing capability. Another type of application would be one that attempted to determine the range of values that each variable within the program could have at run-time, based on an "abstract interpretation" or a data and control flow analysis of its logic. This is similar to an interpreter, except that it does not construct an entire run-time context, but rather an abstraction of it that allows run-time properties to be approximated, generally through an iterative algorithm that stabilizes on a fixed-point approximation. BASIC SEMANTIC MODEL The existing ASIS packages define "Elements" which correspond roughly to syntactic "constructs." We propose to define "entities" and "views" thereof that represent the semantic entities defined by the syntactic constructs. In some cases, there is almost a one-to-one correspondence between the entity and the construct, for example, with an exception. For others, such as a "object view" there may be many different kinds of constructs that create object views which nevertheless have relatively similar properties. Here are the kinds of entities and views we propose to include in our ASIS semantic model: - Program_Unit_View - Package_View - Subprogram_View - Task_Unit - Protected_Unit - Generic_View - Single_Entry - Entry_Family - Subtype_View - Object_View - Callable_View - Exception In addition, we propose to define certain other abstractions that allow us to characterize or manipulate the above entities or views: - Direct_Visibility_View - Declarative_Region_View - Region_Part - Profile We use the term view only when there are multiple views possible for the same underlying entity. For a given subprogram, it is possible to have different formal parameter names and defaults, depending on the view. For a package, there is a limited view (associated with a "limited with"), a partial view (e.g. from the outside), a private view (e.g. from a child), and a full view (e.g. from inside the body). On the other hand, there is only one view of an exception. For a generic, the only thing that can vary by the view is the name of the generic, so it may not be worth considering these different views. Many entities and views of entities have declarative regions associated with them. We propose to represent a particular view of a declarative region as a set of "region parts," one for each distinct part of a declarative region. Here are the different kinds of region parts: - generic formal part - discriminant part - formal part - visible part - private part - public child part - private child part - body part In addition to being able to iterate through the declarations of a region part, we propose to support the lookup of an identifier within a region part, within a declarative region view, or within a direct visibility view. If the lookup is successful, the result would be a single non-overloadable declaration, or a list of overloadable declarations. A direct visibility view supports lookups in a particular context, looking into enclosing scopes and taking use visibility into account. Looking up in a region part or a declarative region view does not worry about enclosing scopes or use visibility, and corresponds more closely to what would be called "selective visibility." Because we are proposing a relatively large set of interfaces, we are not currently proposing wording, but rather are working to specify the queries to be provided using a more economical syntax than full Ada package specifications. Once we agree on the set of interfaces to be provided, we will then create actual Ada packages with corresponding detailed descriptions for each operation. DETAILED SEMANTIC MODEL In this section, we define the operations that can be performed on the various kinds of entities and views. The operations available are listed underneath each kind of entity/view. The operations are defined in a notation such as: Subtype_View: ... Is_Derived -> Boolean Parent_Subtype -> Subtype_View Is_Descendant(Subtype_View) -> Boolean The above means that the operation Is_Derived is defined on Subtype_Views and (implicitly) takes one parameter being a Subtype_View, and returns a Boolean result. The indented Parent_Subtype operation is defined only if the Is_Derived operations returns True, and it returns a Subtype_View as a result. Finally, the "Is_Descendant" operation is defined on Subtype_Views, and in addition to the (implicit) first parameter being Subtype_View, this takes an additional parameter (also a Subtype_View in this case), and returns a Boolean result. Hopefully this notation will be sufficiently clear to allow the set of operations to be understood and relatively easily updated, without worrying about continually revising a lot of Ada subprogram specifications. As indicated above, once we settle on the desired interfaces, we can write out the package specifications in full detail. Semantic Attributes: Entity_Or_View Kind_Of_Entity -> enum Expr_Denoting_Entity -> ASIS.Expression Has_Declaration -> Boolean Entity_Declaration -> ASIS.Declaration Entity_Identifier -> ASIS.Identifier Is_Overloadable -> Boolean Enclosing_Scope -> Declarative_Region Logical_Position_In_Region -> Natural Enclosing_Compilation_Unit -> ASIS.Compilation_Unit Is_Renaming -> Boolean Renamed_Entity -> Entity Is_Program_Unit -> Boolean Has_Body -> Boolean Entity_Body -> ASIS.Declaration Has_Stub -> Boolean Entity_Stub -> ASIS.Declaration Is_Compilation_Unit -> Boolean Is_Library_Unit -> Boolean Parent_Library_Unit -> Entity Representation_Items -> List of Representation_Items Contains_Declarative_Region -> Boolean Contained_Region -> Declarative_Region Region_Part Kind_Of_Region_Part -> enum (Generic_Formal_Part, Formal_Part, Discriminant_Part, Entry_Family_Index_Part, Record_Part, Extension_Part, Package_Visible_Part, Package_Private_Part, Task_Visible_Part, Task_Private_Part, Protected_Visible_Part, Protected_Private_Part, Body_Part, Block_Declarative_Part, Loop_Declarative_Part, Child_Part) Enclosing_Region -> Declarative_Region Declarations -> List of Entitities Lookup(Identifier) -> List of Entity_Or_View Declarative_Region -> Enclosing_Entity -> Entity Has_Generic_Formal_Part -> Boolean Generic_Formal_Part -> Region_Part Visible_Parts -> List of Region_Parts Private_Part -> Region_Part (may be empty) Body_Part -> Region_Part (may be empty) Declarative_Region_View -> Region -> Declarative_Region Visible_Position_In_Region -> Natural Introduced_Position_In_Region -> Natural Visible_Children -> Set of Declarative_Region_Views Lookup(Identifier) -> Entity_Or_View Direct_Visibility_View -> Visibility_Stack -> List of Declarative_Region_Views Use_Visibility -> Set of Package_Views + Set of Subtype_Views Subprogram_View Subprogram_Profile -> Profile Is_Instance -> Boolean Instantiated_Generic -> Generic_Subprogram Actual_Part -> List of Associations Is_Abstract -> Boolean Is_Overriding -> Boolean Overrides -> Set of Subprograms Is_Null -> Boolean Is_Primitive -> Boolean Primitive_On_Types -> Set of Subtypes Is_Dispatching_Operation -> Boolean Associated_Tagged_Type -> Subtype_View Package_View Is_Limited_View -> Boolean Full_View -> Package View Is_Instance -> Boolean Instantiated_Generic -> Generic_Package Actual_Part -> List of Associations Is_Formal_Package -> Boolean Is_Pure -> Boolean Is_Preelaborated -> Boolean Is_Remote_Call_Interface -> Boolean Is_Remote_Types_Package -> Boolean Generic Entity Formal_Part -> Region_Part Current_Instance -> Entity Subtype_View Category -> {boolean, character, ordinary_enum, signed int, modular int, ordinary fixed, decimal fixed, float, access-to-obj, access-to-subp, record, record extension, array, task, protected, interface, private, private extension} Are_Of_Same_Type(Subtype_View) -> Boolean Is_First_Subtype -> Boolean Is_Secondary_Subtype -> Boolean Preconstraint_Subtype -> Subtype_View Constraint -> ASIS.Constraint First_Subtype -> Subtype_View Primitive_Subprograms -> List of Subprograms Is_Formal_Type -> Boolean Is_Aspect_Specified(Aspect) -> Boolean Is_Aspect_Directly_Specified(Aspect) -> Boolean Is_Constrained -> Boolean Constraint -> ASIS.Constraint Is_Definite -> Boolean Is_Derived -> Boolean Parent_Subtype -> Subtype_View Ultimate_Ancestor -> Subtype_View Is_Descendant(Subtype_View) -> Boolean Is_Ancestor(Subtype_View) -> Boolean Is_Incomplete_View -> Boolean Complete_View -> Subtype_View Is_Partial_View -> Boolean Full_View -> Subtype_View Is_Elementary -> Boolean Is_Universal -> Boolean Is_Scalar -> Boolean Base_Subtype -> Subtype_View Low_Bound,High_Bound -> Expression/Value/? Is_Discrete -> Boolean Is_Access -> Boolean Is_Anonymous_Access -> Boolean Is_Access_Parameter_Subtype -> Boolean Is_Access_Result_Subtype -> Boolean Static_Accessibility -> Natural Excludes_Null -> Boolean Is_Access_To_Object -> Boolean Designated_Subtype -> Subtype_View Is_Access_To_Constant -> Boolean Is_Pool_Specific -> Boolean Is_Access_To_Subprogram -> Boolean Designated_Profile -> Profile Is_Composite -> Boolean Is_Record -> Boolean Is_Array -> Boolean Is_Protected -> Boolean Is_Task -> Boolean Is_Tagged -> Boolean Is_Classwide -> Boolean Root_Subtype -> Subtype_View Is_Specific_Tagged -> Boolean Classwide_Subtype -> Subtype_View Is_Synchronized_Tagged -> Boolean Is_Interface -> Boolean Is_Abstract -> Boolean Progenitors -> List of Subtype_Views Has_Known_Discriminants -> Boolean Discriminants -> Region_Part Has_Unknown_Discriminants -> Boolean Has_Nondiscriminant_Components -> Boolean Nondiscriminant_Components -> Region_Part Is_Limited -> Boolean Has_Preelaborable_Initialization -> Boolean Needs_Finalization -> Boolean Contains_Task -> Boolean Object_View Nominal_Subtype -> Subtype_View Is_Component -> Boolean Enclosing_Object -> Object_View Is_Constant_View -> Boolean Is_Aliased_View -> Boolean Static_Accessibility -> Natural Callable_View Callable_Profile -> Profile Denoted_Callable_Unit -> Callable_Unit Is_Prefixed_View -> Boolean Prefix_Object -> Object_View Unprefixed_Callable_View -> Callable_View Profile Parameters -> Region_Part Has_Result_Subtype -> Boolean Result_Subtype -> Subtype_View Has_Family_Index -> Boolean Family_Index_Definition -> Subtype_View Convention -> enum (Intrinsic_Convention, Ada_Convention, Protected_Convention, Entry_Convention, Other_Convention, Unspecified_Convention) Convention_Identifier -> ASIS.Identifier ----------------------- Additional thoughts 11/15/06: Additional operations: Are_Views_Of_Same_Entity(Other_View) -> Boolean Syntax -> Semantic linkages Need some way to get direct-visibility-view from a point in the AST Every declaration/name/expression needs linkage to entity/view Unlike the AST, the objects representing views might not exist until requested. They are more like handles into the symbol table. Prefixed views are a problem, since they are always implicit. Build this incrementally based on needs, e.g. for dispatching calls, for prefixed views, for inherited operations. Is_Implicit_Dereference, Is_Implicit_Tick_Access Corresponding_Representation_Clauses (Aspects, Representation_Items) should be associated with individaul entities, since two entities with the same syntactic declaration can have different representation. Drop the region view lookup stuff Keep the region part stuff Keep the ordering No child part Slice? (enclosing) Is_Value(object-view) Is_Object(object-view) Links from existing ASIS expression -> object view name -> entity_or_view require ASIS expressions under certain circumstances such as for defaults, parameter specifications, formal parameters make it clear what is not provided for implicit expressions, etc. ------------------------------------------- PACKAGE SPECIFICATION In deciding how to represent the above semantic attribute queries as an Ada package, there were a number of significant issues to be decided. Most basically was how to refer to entities or views. ASIS uses the single type Element for essentially every syntactic construct, and then defines "trivial" subtypes which can be used to aid in readability. This existing ASIS approach sacrifices all compile-time checking in the use of the ASIS structural queries, which seems a shame. We would prefer to have some kind of type checking to help find misuses of the newly defined semantic queries at compile time. Given the desire to use multiple types to distinguish different kinds of entities, we then face the issue of limited vs. non-limited, tagged vs. non-tagged, interfaces vs. non-interfaces, explicitly derived vs. conversion functions, explicit pointers vs. opaque references, etc. We had various criteria which led to our current proposal of using a non-tagged hierarchy of discriminated types. One goal was to permit declaring variables whose underlying entity kind might not be known at the point of declaration. Similarly, we wanted to be able to manipulate heterogeneous lists of semantic entities. Both of these create issues when using tagged types, since only class-wide types allow heterogeneity, and those require explicit initialization. An alternative would be to use explicit pointers everywhere, but this could introduce a significant storage management and/or dangling reference burden on the user of the semantic queries. If we decide to use non-tagged, non-pointer types, we clearly want to use non-limited types to allow assignment after initialization. If we decide to use tagged, non-pointer types, then we need to define some kind of "holder" object that can be used to hold one object of a class-wide type, but need not be initialized on declaration, and can appear as a component of a record or array. With untagged types, choosing between explicitly derived types and types that have explicit conversion functions was based on reducing the number of explicit conversions required and/or reducing the number of redundant declarations for queries that are shared across the type hierarchy. The final decision was whether to incorporate any kind of run-time check at the point of conversion to a descendant type (a so-called "narrowing" conversion), or leave the run-time checking to each query. Clearly it seemed preferable to incorporate a check at the point of conversion where feasible. For untagged types, this can be accomplished by defining a "kind" enumeration, using it as a discriminant of the root type, and then using subtypes of the enumeration as the discriminant for descendant types. This works well for a strict hierarchy, but does not work as well when there are non-hierarchical classifications, such as distinguishing between declared vs. constructed views. In the latter case, we fall back to relying on checks on each query. For tagged types, we naturally want to rely on the usual rules for conversion, where "narrowing" conversions are checked, and "widening" conversions are free (and implicit when the target is class-wide). With judicious use of interface types, we might also handle non-hierarchical classifications, largely eliminating checks on each query. Another set of issues revolved around nomenclature. We have chosen to uniformly use the term "subtype" rather than "type or subtype," and use the term "view" rather than "entity or view" as in both cases, the former simpler term includes both of the latter terms. We also had to decide how to classify the views, and we have chosen six basic groups: object views, callable views, subtype views, package views, exception views, and generic views. We considered "typed views" rather than "object views," recognizing that there are still some cases where expressions or names denote "values" rather than "objects," but the term "typed view" seemed too close to "subtype view". An alternative for "callable view" might be "subprogram view," treating entries and corresponding accept statements as special cases of subprograms, but we chose the more generic term since calling a task entry a "subprogram" seems likely to cause confusion. A final issue had to do with packaging. We have chosen to name the packages by the major view groupings. An alternative would be to combine them all into a single package. Because of interdependences, we ended up combining object views, subtype views, and profiles in the untagged version. In the tagged version, we broke the packages up a bit more, and managed to avoid the problems with the interdependence. Also, we changed the return type of some of the operations to avoid the interdependence. IMPLEMENTATION USING ADA 95 An Ada 95 version of this would be somewhat harder. Clearly all of the interface types would become "regular" abstract tagged types. However, there is a subtle issue with Declared_Views, since a given type descended from Object_View might or might not want to be a descendant of Declared_View, and that kind of thing implies multiple inheritance. The same goes for Subtype_View and Callable_View. To avoid this problem, we could have a separate type that captures the information associated with a Declared_View, perhaps call it "View_Declaration," and allow any View to have one. That way we wouldn't be depending on multiple inheritance. View_Declaration might be a plain old private type, which would be consistent with the types Region_Part and Declarative_Region used already. !wording --------------------------- --- Tagged type version --- --------------------------- with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); with Ada.Containers.Indefinite_Vectors; pragma Elaborate_All(Ada.Containers.Indefinite_Vectors); package ASIS.Views is type View_Kinds is ( An_Exception, An_Exception_Renaming, A_Generic_Package, A_Generic_Package_Renaming, A_Generic_Subprogram, A_Generic_Subprogram_Renaming, A_Noninstance_Package, A_Package_Instance, A_Package_Renaming, A_Limited_Package_View, A_Noninstance_Subprogram, A_Subprogram_Instance, A_Subprogram_Renaming, A_Protected_Subprogram, An_Imported_Subprogram, An_Attribute_Subprogram, An_Intrinsic_Subprogram, A_Designated_Subprogram, A_Generic_Formal_Subprogram, A_Protected_Entry, A_Task_Entry, A_Standalone_Object, A_Generic_Formal_Object, A_Formal_Parameter_Object, An_Object_Renaming, A_Designated_Object, A_Component_Object, An_Attribute_Object, An_Aggregate_Object, A_Function_Result_Object, A_Named_Number, An_Attribute_Value, An_Expr_Value, A_Boolean_Subtype, A_Character_Subtype, An_Ordinary_Enumeration_Subtype, A_Signed_Integer_Subtype, A_Modular_Integer_Subtype, An_Ordinary_Fixed_Subtype, A_Decimal_Fixed_Subtype, A_Float_Subtype, An_Access_To_Object_Subtype, An_Access_To_Subprogram_Subtype, An_Array_Subtype, A_Record_Subtype, A_Record_Extension, A_Task_Subtype, A_Protected_Subtype, An_Interface, A_Private_Subtype, A_Private_Extension, An_Incomplete_Subtype ); subtype Exception_View_Kinds is View_Kinds range An_Exception .. An_Exception_Renaming; subtype Generic_View_Kinds is View_Kinds range A_Generic_Package .. A_Generic_Subprogram_Renaming; subtype Callable_View_Kinds is View_Kinds range A_Noninstance_Subprogram .. A_Task_Entry; subtype Object_View_Kinds is View_Kinds range A_Standalone_Object .. An_Expr_Value; subtype Subtype_View_Kinds is View_Kinds range A_Boolean_Subtype .. An_Incomplete_Subtype; subtype Package_View_Kinds is View_Kinds range A_Noninstance_Package..A_Limited_Package_View; type View is interface; package View_Holders is new Ada.Containers.Holders(View'Class); type View_Holder is new View_Holders.Holder with null record; package View_Vectors is new Ada.Containers.Indefinite_Vectors(Positive, View'Class); type View_Vector is new View_Vectors.Vector with null record; function Kind(V : View) return View_Kinds is abstract; function Expr_Denoting_View(V : View) return ASIS.Expression is abstract; function Has_Declaration(V : View) return Boolean is abstract; function Is_Exception(V : View) return Boolean is abstract; function Is_Generic(V : View) return Boolean is abstract; function Is_Callable(V : View) return Boolean is abstract; function Is_Object_Or_Value(V : View) return Boolean is abstract; function Is_Subtype(V : View) return Boolean is abstract; function Is_Package(V : View) return Boolean is abstract; type Conventions is ( Intrinsic_Convention, Ada_Convention, Protected_Convention, Entry_Convention, Other_Convention, Unspecified_Convention); function Convention(V : View) return Conventions is abstract; function Convention_Identifier(V : View) return ASIS.Identifier is abstract; package Declarative_Regions is type Declarative_Region is private; type Region_Part is private; type Region_Part_Array is array(Positive range <>) of Region_Part; type Region_Part_Kinds is (Generic_Formal_Part, Callable_Formal_Part, Discriminant_Part, Entry_Family_Index_Part, Record_Part, Extension_Part, Package_Visible_Part, Package_Private_Part, Task_Visible_Part, Task_Private_Part, Protected_Visible_Part, Protected_Private_Part, Body_Part, Block_Declarative_Part, Loop_Declarative_Part, Child_Part); function Kind(P : Region_Part) return Region_Part_Kinds; function Declarations(P : Region_Part) return ASIS.Declarative_Item_List; --?? Should this be a vector of (declared) views? function All_Region_Parts(R : Declarative_Region) return Region_Part_Array; function Visible_Region_Parts(R : Declarative_Region) return Region_Part_Array; function Private_Part(R : Declarative_Region) return Region_Part; function Body_Part(R : Declarative_Region) return Region_Part; function Is_Empty(P : Region_Part) return Boolean; function Defining_Entity(R : Declarative_Region) return View'Class; function Enclosing_Region(P : Region_Part) return Declarative_Region; end Declarative_Regions; function Defines_Declarative_Region(V : View) return Boolean is abstract; function Defined_Region(V : View) return Declarative_Regions.Declarative_Region is abstract; end ASIS.Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with Ada.Containers.Indefinite_Vectors; pragma Elaborate_All(Ada.Containers.Indefinite_Vectors); package ASIS.Declared_Views is type Declared_View is interface and View; function View_Declaration(V : Declared_View) return ASIS.Declaration is abstract; function View_Identifier(V : Declared_View) return ASIS.Identifier is abstract; function Is_Overloadable(V : Declared_View) return Boolean is abstract; function Is_Overriding(V : Declared_View) return Boolean is abstract; function Overridden_Entity(V : Declared_View) return Declared_View'Class is abstract; function Representation_Items(V : Declared_View) return ASIS.Representation_Clause_List is abstract; function Enclosing_Region(V : Declared_View) return Declarative_Region is abstract; function Enclosing_Region_Part(V : Declared_View) return Region_Part is abstract; function Expanded_Name(V : Declared_View) return String is abstract; function Wide_Expanded_Name(V : Declared_View) return Wide_String is abstract; function Wide_Wide_Expanded_Name(V : Declared_View) return Wide_Wide_String is abstract; type Logical_Position is new Natural; function Logical_Position_In_Region(V : Declared_View) return Logical_Position is abstract; function Enclosing_Compilation_Unit(V : Declared_View) return ASIS.Compilation_Unit is abstract; function Is_Renaming(V : Declared_View) return Boolean is abstract; function Renamed_View(V : Declared_View) return View'Class is abstract; function Is_Program_Unit(V : Declared_View) return Boolean is abstract; type Program_Unit is interface and Declared_View; package Program_Unit_Vectors is new Ada.Containers.Indefinite_Vector(Positive, Program_Unit'Class); type Program_Unit_Vector is new Program_Unit_Vectors.Vector with null record; function Needs_Body(P : Program_Unit) return Boolean is abstract; function Has_Body(P : Program_Unit) return Boolean is abstract; function Body_Of_Program_Unit(P : Program_Unit) return ASIS.Declaration is abstract; function Has_Stub(P : Program_Unit) return Boolean is abstract; function Stub_Of_Program_Unit(P : Program_Unit) return ASIS.Declaration is abstract; function Is_Instance(P : Program_Unit) return Boolean is abstract; function Instantiated_Generic(P : Program_Unit) return Program_Unit'Class is abstract; function Actual_Part(P : Program_Unit) return ASIS.Association_List is abstract; function Is_Compilation_Unit(P : Program_Unit) return Boolean is abstract; function Depends_Semantically_On(P : Program_Unit) return Program_Unit_Vector is abstract; function Is_Library_Item(P : Program_Unit) return Boolean is abstract; type Library_Item is interface and Program_Unit; function Has_Parent_Library_Unit(L : Library_Item) return Boolean is abstract; function Parent_Library_Unit(L : Library_Item) return Library_Item'Class is abstract; function Is_Pure(L : Library_Item) return Boolean is abstract; function Is_Preelaborated(L : Library_Item) return Boolean is abstract; function Is_Remote_Call_Interface(L : Library_Item) return Boolean is abstract; function Is_Remote_Types_Package(L : Library_Item) return Boolean is abstract; end ASIS.Declared_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); with Ada.Containers.Indefinite_Vectors; pragma Elaborate_All(Ada.Containers.Indefinite_Vectors); package ASIS.Subtype_Views is type Subtype_View is interface and View; package Subtype_Holders is new Ada.Containers.Holders(Subtype_View'Class); type Subtype_Holder is new Subtype_Holders.Holder; package Subtype_Vectors is new Ada.Containers.Indefinite_Vectors(Positive, Subtype_View'Class); type Subtype_Vector is new Subtype_Vectors.Vector; function Is_Elementary(S : Subtype_View) return Boolean is abstract; function Is_Composite(S : Subtype_View) return Boolean is abstract; function Is_Scalar(S : Subtype_View) return Boolean is abstract; function Is_Enumeration(S : Subtype_View) return Boolean is abstract; function Is_Numeric(S : Subtype_View) return Boolean is abstract; function Is_Discrete(S : Subtype_View) return Boolean is abstract; function Is_Integer(S : Subtype_View) return Boolean is abstract; function Is_Real(S : Subtype_View) return Boolean is abstract; function Is_Fixed_Point(S : Subtype_View) return Boolean is abstract; function Is_Floating_Point(S : Subtype_View) return Boolean is abstract; function Is_Access(S : Subtype_View) return Boolean is abstract; function Is_Access_To_Object(A : Subtype_View) return Boolean is abstract; function Is_Access_To_Subprogram(A : Subtype_View) return Boolean is abstract; function Is_Record(C : Subtype_View) return Boolean is abstract; function Is_Record_Extension(C : Subtype_View) return Boolean is abstract; function Is_Array(C : Subtype_View) return Boolean is abstract; function Is_Protected(C : Subtype_View) return Boolean is abstract; function Is_Task(C : Subtype_View) return Boolean is abstract; function Is_Tagged(C : Subtype_View) return Boolean is abstract; function Are_Of_Same_Type(Left, Right : Subtype_View) return Boolean is abstract; function Is_First_Subtype(S : Subtype_View) return Boolean is abstract; function Is_Secondary_Subtype(S : Subtype_View) return Boolean is abstract; functino Preconstraint_Subtype(S : Subtype_View) return Subtype_View'Class is abstract; function Constraint(S : Subtype_View) return ASIS.Constraint is abstract; function First_Subtype(S : Subtype_View) return Subtype_View'Class is abstract; function Primitive_Subprograms(S : Subtype_View) return ASIS.Declarative_Item_List is abstract; --?? should this be a vector of Declared_Views or Callable_Views function Is_Formal_Subtype(S : Subtype_View) return Boolean is abstract; function Is_Descended_From_Formal_Subtype(S : Subtype_View) return Boolean is abstract; type Aspect_Kinds is ( A_Size_Aspect, An_Alignment_Aspect, An_Address_Aspect, A_Position_Aspect, ...); function Is_Aspect_Specified(Aspect : Aspect_Kinds) return Boolean is abstract; function Is_Aspect_Directly_Specified(Aspect : Aspect_Kinds) return Boolean is abstract; function Is_Static_Subtype(S : Subtype_View) return Boolean is abstract; function Is_Constrained(S : Subtype_View) return Boolean is abstract; function Is_Statically_Constrained(S : Subtype_View) return Boolean is abstract; function Constraint(S : Subtype_View) return ASIS.Constraint is abstract; function Are_Statically_Matching(S1, S2 : Subtype_View) return Boolean is abstract; function Is_Statically_Compatible(S : Subtype_View; With_Subtype : Subtype_View) return Boolean is abstract; function Is_Definite(S : Subtype_View) return Boolean is abstract; function Is_Derived_Subtype(S : Subtype_View) return Boolean is abstract; function Parent_Subtype(S : Subtype_View) return Subtype_View'Class is abstract; function Ultimate_Ancestor(S : Subtype_View) return Subtype_View'Class is abstract; function Is_Descendant(S : Subtype_View; Of_Subtype : Subtype_View) return Boolean is abstract; function Is_Incomplete_View(S : Subtype_View) return Boolean is abstract; function Complete_View(S : Subtype_View) return Subtype_View'Class is abstract; function Is_Partial_View(S : Subtype_View) return Boolean is abstract; function Full_View(S : Subtype_View) return Subtype_View'Class is abstract; function Subtype_Size(S : Subtype_View) return Natural is abstract; -- Returns equivalent to 'Size when subtype is elementary or -- size is specified. Result is implementation-defined in -- other cases, and may be Natural'Last. function Subtype_Alignment(S : Subtype_View) return Natural is abstract; end ASIS.Subtype_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Subtype_Views; use ASIS.Subtype_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); package ASIS.Object_Views is ----------------------------------- -- Object Views (Includes "pure" values) ----------------------------------- type Object_View is interface and View; package Object_Holders is new Ada.Containers.Holders(Object_View'Class); type Object_Holder is new Object_Holders.Holder; function Nominal_Subtype(O : Object_View) return Subtype_View'Class is abstract; function Is_Component(O : Object_View) return Boolean is abstract; function Enclosing_Object(O : Object_View) return Object_View is abstract; function Position(O : Object_View) return Natural is abstract; -- This returns the same as 'Position if specified. -- The result is implementation-defined in other cases, -- and may be Natural'Last. function Is_Constant(O : Object_View) return Boolean is abstract; function Is_Aliased(O : Object_View) return Boolean is abstract; function Static_Accessibility(O : Object_View) return Static_Accessibility_Level is abstract; function Is_Designated_Object(O : Object_View) return Boolean is abstract; function Is_Implicit_Dereference(O : Object_View) return Boolean is abstract; function Is_Implicit_Tick_Access(O : Object_View) return Boolean is abstract; function Is_Static_Integer(O : Object_View) return Boolean is abstract; function Static_Integer_Value(O : Object_View) return Longest_Integer is abstract; function Is_Static_Real(O : Object_View) return Boolean is abstract; function Static_Real_Value(O : Object_View) return Longest_Float is abstract; function Is_Static_String(O : Object_View) return Boolean is abstract; function Static_String_Value(O : Object_View) return String is abstract; function Static_Wide_String_Value(O : Object_View) return Wide_String is abstract; function Static_Wide_Wide_String_Value(O : Object_View) return Wide_Wide_String is abstract; function Object_Size(O : Object_View) return Natural is abstract; -- This returns the same as 'Size if object is elementary -- or its size or its subtype's size is specified. -- The result is implementation-defined in other cases, -- and may be Natural'Last. function Object_Alignment(O : Object_View) return Natural is abstract; end ASIS.Object_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Subtype_Views; use ASIS.Subtype_Views; package ASIS.Profiles is -------------------------------- -- Parameter and Result Profiles -------------------------------- function Parameters(P : Profile) return Region_Part; function Is_Function(P : Profile) return Boolean; function Result_Subtype(P : Profile) return Subtype_View; function Has_Family_Index(P : Profile) return Boolean; function Family_Index_Subtype(P : Profile) return Subtype_View; function Convention(P : Profile) return Conventions; function Convention_Identifier(P : Profile) return ASIS.Identifier; end ASIS.Profiles; --------------------------------------------------------------- with ASIS.Object_Views; use ASIS.Object_Views; with ASIS.Profiles; use ASIS.Profiles; package ASIS.Subtype_Views.Elementary is ------------------------------ -- Elementary Subtype Views -- ------------------------------ type Elementary_Subtype is interface and Subtype_View; type Scalar_Subtype is interface and Elementary_Subtype; function Base_Subtype(S : Scalar_Subtype) return Scalar_Subtype'Class is abstract; function Low_Bound(S : Scalar_Subtype) return Object_View'Class is abstract; function High_Bound(S : Scalar_Subtype) return Object_View'Class is abstract; --?? Enumeration, Integer, Fixed, Floating -- are separate types needed? type Access_Subtype is interface and Elementary_Subtype; function Is_Anonymous_Access(A : Access_Subtype) return Boolean is abstract; function Is_Access_Parameter(A : Access_Subtype) return Boolean is abstract; function Is_Access_Result(A : Access_Subtype) return Boolean is abstract; function Is_Access_Discriminant(A : Access_Subtype) return Boolean is abstract; type Static_Accessibility_Level is new Natural; function Static_Accessibility(A : Access_Subtype) return Static_Accessibility_Level is abstract; function Excludes_Null(A : Access_Subtype) return Boolean is abstract; type Access_To_Object_Subtype is interface and Access_Subtype; function Designated_Subtype(A : Access_To_Object_Subtype) return Subtype_View'Class is abstract; function Is_Access_To_Constant(A : Access_To_Object_Subtype) return Boolean is abstract; function Is_Pool_Specific(A : Access_To_Object_Subtype) return Boolean is abstract; function Storage_Pool(A : Access_To_Object_Subtype) return Object_View'Class is abstract; function Storage_Size(A : Access_To_Object_Subtype) return Object_View'Class is abstract; type Access_To_Subprogram_Subtype is interface and Access_Subtype; function Designated_Profile(A : Access_To_Subprogram_Subtype) return Profile is abstract; end ASIS.Subtype_Views.Elementary; --------------------------------------------------------------- package ASIS.Subtype_Views.Composite is ----------------------------- -- Composite Subtype Views -- ----------------------------- type Composite_Subtype is interface and Subtype_View; function Is_Limited(C : Composite_Subtype) return Boolean is abstract; type Array_Subtype is interface and Composite_Subtype; function Component_Subtype(A : Array_Subtype) return Subtype_View'Class is abstract; function Num_Dimensions(A : Array_Subtype) return Positive is abstract; function Index_Subtype(A : Array_Subtype; Dimension : Positive := 1) return Discrete_Subtype'Class is abstract; function Is_String_Subtype(A : Array_Subtype) return Boolean is abstract; function Contains_Task(C : Composite_Subtype) return Boolean is abstract; function Needs_Finalization(C : Composite_Subtype) return Boolean is abstract; function Has_Preelaborable_Initialization(C : Composite_Subtype) return Boolean is abstract; function Has_Unknown_Discriminants(C : Composite_Subtype) return Boolean is abstract; function Has_Known_Discriminants(C : Composite_Subtype) return Boolean is abstract; function Discriminants(C : Composite_Subtype) return Declarative_Regions.Region_Part is abstract; function Discriminants_Have_Defaults(C : Composite_Subtype) return Boolean is abstract; function Has_Nondiscriminant_Components(C : Composite_Subtype) return Boolean is abstract; function Nondiscriminant_Components(C : Composite_Subtype) return Declarative_Regions.Region_Part_Array is abstract; -- NOTE: Return an array of region parts to handle -- case of multiple extension parts, or -- visible and private parts of task/protected types type Tagged_Subtype is interface and Composite_Subtype; package Tagged_Subtype_Vectors is new Ada.Containers.Indefinite_Vectors(Positive, Tagged_Subtype'Class); type Tagged_Subtype_Vector is new Tagged_Subtype_Vectors.Vector with null record; function Is_Interface(T : Tagged_Subtype) return Boolean is abstract; function Is_Abstract(T : Tagged_Subtype) return Boolean is abstract; function Is_Synchronized_Tagged(T : Tagged_Subtype) return Boolean is abstract; function Is_Classwide(T : Tagged_Subtype) return Boolean is abstract; function Root_Subtype(T : Tagged_Subtype) return Tagged_Subtype'Class is abstract; function Is_Specific(T : Tagged_Subtype) return Boolean is abstract; function Classwide_Subtype(T : Tagged_Subtype) return Tagged_Subtype'Class is abstract; function Progenitors(T : Tagged_Subtype) return Tagged_Subtype_Vector is abstract; function External_Tag(T : Tagged_Subtype) return String is abstract; end ASIS.Subtype_Views.Composite; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Subtype_Views; use ASIS.Subtype_Views; with ASIS.Subtype_Views.Composite; with ASIS.Profiles; use ASIS.Profiles; with ASIS.Object_Views; use ASIS.Object_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); package ASIS.Callable_Views is type Callable_View is interface and View; package Callable_Holders is new Ada.Containers.Holders(Callable_View'Class); type Callable_Holder is new Callable_Holders.Holder; function Callable_Profile(C : Callable_View) return Profile is abstract; function Is_Subprogram(C : Callable_View) return Boolean is abstract; function Is_Enumeration_Literal(C : Callable_View) return Boolean is abstract; function Is_Entry(C : Callable_View) return Boolean is abstract; function Is_Function(C : Callable_View) return Boolean is abstract; function Is_Abstract(C : Callable_View) return Boolean is abstract; function Is_Null(C : Callable_View) return Boolean is abstract; function Is_Primitive(C : Callable_View) return Boolean is abstract; function Primitive_On_Subtypes(C : Callable_View) return Subtype_Vector is abstract; function Is_Dispatching_Operation(C : Callable_View) return Boolean is abstract; function Associated_Tagged_Type(C : Callable_View) return Composite.Tagged_Subtype'Class is abstract; function Is_Prefixed_View(C : Callable_View) return Boolean is abstract; function Prefix_Object(C : Callable_View) return Object_View'Class is abstract; function Unprefixed_Callable_View(C : Callable_View) return Callable_View'Class is abstract; function Is_Designated_Subprogram(C : Callable_View) return Boolean is abstract; end ASIS.Callable_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); package ASIS.Package_Views is type Package_View is interface and Program_Unit; package Package_Holders is new Ada.Containers.Holders(Package_View'Class); type Package_Holder is new Package_Holders.Holder; function Is_Limited_View(P : Package_View) return Boolean is abstract; function Full_View(P : Package_View) return Package_View'Class is abstract; function Is_Full_View(P : Package_View) return Boolean is abstract; function Limited_View(P : Package_View) return Package_View'Class is abstract; function Is_Formal_Package(P : Package_View) return Boolean is abstract; function Visible_Part(P : Package_View) return Declaration_Regions.Region_Part is abstract; end ASIS.Package_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; with ASIS.Callable_Views; with ASIS.Package_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); package ASIS.Generic_Views is type Generic_View is interface and Program_Unit; package Generic_Holders is new Ada.Containers.Holders(Generic_View'Class); type Generic_Holder is new Generic_Holders.Holder; function Generic_Formal_Part(G : Generic_View) return Declarative_Regions.Region_Part is abstract; function Is_Generic_Package(G : Generic_View) return Boolean is abstract; function Current_Package_Instance(G : Generic_View) return Package_Views.Package_View'Class is abstract; function Is_Generic_Subprogram(G : Generic_View) return Boolean is abstract; function Current_Subprogram_Instance(G : Generic_View) return Callable_Views.Callable_View'Class is abstract; end ASIS.Generic_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; with Ada.Containers.Holders; pragma Elaborate_All(Ada.Containers.Holders); package ASIS.Exception_Views is type Exception_View is interface and Declared_View; package Exception_Holders is new Ada.Containers.Holders(Exception_View'Class); type Exception_Holder is new Exception_Holders.Holder; function Names_Are_Discarded(E : Exception_View) return Boolean is abstract; end ASIS.Exception_Views; --------------------------------------------------------------- Add at end of ASIS.Declarations: function Corresponding_Declared_View( Declaration: in ASIS.Declaration) return ASIS.Declared_Views.Declared_View'Class; Add at end of ASIS.Definitions: function Corresponding_Subtype_View( Type_Definition : in ASIS.Type_Definition) return ASIS.Subtype_Views.Subtype_View'Class; Add at end of ASIS.Expressions: function Corresponding_View( Expression : in ASIS.Expression) return ASIS.Views.View'Class; ====================== end of "tagged" version ============================== --------------------------------------- --- Untagged, Discriminated version --- --------------------------------------- package ASIS.Views is type View_Kinds is ( An_Exception, An_Exception_Renaming, A_Generic_Package, A_Generic_Package_Renaming, A_Generic_Subprogram, A_Generic_Subprogram_Renaming, A_Noninstance_Package, A_Package_Instance, A_Package_Renaming, A_Limited_Package_View, A_Noninstance_Subprogram, A_Subprogram_Instance, A_Subprogram_Renaming, A_Protected_Subprogram, An_Imported_Subprogram, An_Attribute_Subprogram, An_Intrinsic_Subprogram, A_Designated_Subprogram, A_Generic_Formal_Subprogram, A_Protected_Entry, A_Task_Entry, A_Standalone_Object, A_Generic_Formal_Object, A_Formal_Parameter_Object, An_Object_Renaming, A_Designated_Object, A_Component_Object, An_Attribute_Object, An_Aggregate_Object, A_Function_Result_Object, A_Named_Number, An_Attribute_Value, An_Expr_Value, A_Boolean_Subtype, A_Character_Subtype, An_Ordinary_Enumeration_Subtype, A_Signed_Integer_Subtype, A_Modular_Integer_Subtype, An_Ordinary_Fixed_Subtype, A_Decimal_Fixed_Subtype, A_Float_Subtype, An_Access_To_Object_Subtype, An_Access_To_Subprogram_Subtype, An_Array_Subtype, A_Record_Subtype, A_Record_Extension, A_Task_Subtype, A_Protected_Subtype, An_Interface, A_Private_Subtype, A_Private_Extension, An_Incomplete_Subtype ); subtype Exception_View_Kinds is View_Kinds range An_Exception .. An_Exception_Renaming; subtype Generic_View_Kinds is View_Kinds range A_Generic_Package .. A_Generic_Subprogram_Renaming; subtype Callable_View_Kinds is View_Kinds range A_Noninstance_Subprogram .. A_Task_Entry; subtype Object_View_Kinds is View_Kinds range A_Standalone_Object .. An_Expr_Value; subtype Subtype_View_Kinds is View_Kinds range A_Boolean_Subtype .. An_Incomplete_Subtype; subtype Package_View_Kinds is View_Kinds range A_Noninstance_Package..A_Limited_Package_View; type View(Kind : View_Kinds := View_Kinds'First) is private; function Expr_Denoting_View(V : View) return ASIS.Expression; function Has_Declaration(V : View) return Boolean; function Is_Exception(V : View) return Boolean; function Is_Generic(V : View) return Boolean; function Is_Callable(V : View) return Boolean; function Is_Object(V : View) return Boolean; function Is_Subtype(V : View) return Boolean; type Conventions is ( Intrinsic_Convention, Ada_Convention, Protected_Convention, Entry_Convention, Other_Convention, Unspecified_Convention); function Convention(V : View) return Conventions; function Convention_Identifier(V : View) return ASIS.Identifier; end ASIS.Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; package ASIS.Declared_Views is type Declared_View is new View; type Declarative_Region is private; type Region_Part is private; type Region_Part_Array is array(Positive range <>) of Region_Part; type Region_Part_Kinds is (Generic_Formal_Part, Callable_Formal_Part, Discriminant_Part, Entry_Family_Index_Part, Record_Part, Extension_Part, Package_Visible_Part, Package_Private_Part, Task_Visible_Part, Task_Private_Part, Protected_Visible_Part, Protected_Private_Part, Body_Part, Block_Declarative_Part, Loop_Declarative_Part, Child_Part); function Kind(P : Region_Part) return Region_Part_Kinds; function View_Declaration(V : Declared_View) return ASIS.Declaration; function View_Identifier(V : Declared_View) return ASIS.Identifier; function Is_Overloadable(V : Declared_View) return Boolean; function Is_Overriding(V : Declared_View) return Boolean; function Overridden_Entity(V : Declared_View) return Declared_View; function Representation_Items(V : Declared_View) return ASIS.Representation_Clause_List; function Enclosing_Region(V : Declared_View) return Declarative_Region; function Enclosing_Region_Part(V : Declared_View) return Region_Part; function Enclosing_Region(P : Region_Part) return Declarative_Region; function Expanded_Name(V : Declared_View) return String; function Wide_Expanded_Name(V : Declared_View) return Wide_String; function Wide_Wide_Expanded_Name(V : Declared_View) return Wide_Wide_String; type Logical_Position is new Natural; function Logical_Position_In_Region(V : Declared_View) return Logical_Position; function Enclosing_Compilation_Unit(V : Declared_View) return ASIS.Compilation_Unit; function Is_Renaming(V : Declared_View) return Boolean; function Renamed_View(V : Declared_View) return View; function Is_Program_Unit(V : Declared_View) return Boolean; type Program_Unit is new Declared_View; type Program_Unit_Array is array(Positive range <>) of Program_Unit; function Needs_Body(P : Program_Unit) return Boolean; function Has_Body(P : Program_Unit) return Boolean; function Body_Of_Program_Unit(P : Program_Unit) return ASIS.Declaration; function Has_Stub(P : Program_Unit) return Boolean; function Stub_Of_Program_Unit(P : Program_Unit) return ASIS.Declaration; function Is_Instance(P : Program_Unit) return Boolean; function Instantiated_Generic(P : Program_Unit) return Program_Unit; function Actual_Part(P : Program_Unit) return ASIS.Association_List; function Is_Compilation_Unit(P : Program_Unit) return Boolean; function Depends_Semantically_On(P : Program_Unit) return Program_Unit_Array; function Is_Library_Item(P : Program_Unit) return Boolean; type Library_Item is new Program_Unit; function Has_Parent_Library_Unit(L : Library_Item) return Boolean; function Parent_Library_Unit(L : Library_Item) return Library_Item; function Is_Pure(L : Library_Item) return Boolean; function Is_Preelaborated(L : Library_Item) return Boolean; function Is_Remote_Call_Interface(L : Library_Item) return Boolean; function Is_Remote_Types_Package(L : Library_Item) return Boolean; function Declarations(P : Region_Part) return ASIS.Declarative_Item_List; function All_Region_Parts(R : Declarative_Region) return Region_Part_Array; function Visible_Region_Parts(R : Declarative_Region) return Region_Part_Array; function Private_Part(R : Declarative_Region) retrun Region_Part; function Body_Part(R : Declarative_Region) return Region_Part; function Is_Empty(P : Region_Part) return Boolean; function Defines_Declarative_Region(V : View) return Boolean; function Defined_Region(V : View) return Declarative_Region; function Defining_Entity(R : Declarative_Region) return View; end ASIS.Declared_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; package ASIS.Object_Views is -- This one package defines Object_View, Subtype_View, and Profile -- because the three types are interdependent type Object_View(Kind : Object_View_Kinds := Object_View_Kinds'First) is new View(Kind); type Profile is private; type Subtype_View(Kind : Subtype_View_Kinds := Subtype_View_Kinds'First) is new View(Kind); subtype Elementary_Subtype_Kinds is Subtype_View_Kinds range A_Boolean_Subtype .. An_Access_To_Subprogram_Subtype; subtype Composite_Subtype_Kinds is Subtype_View_Kinds range An_Array_Subtype .. An_Incomplete_Subtype; subtype Scalar_Subtype_Kinds is Elementary_Subtype_Kinds range A_Boolean_Subtype .. A_Float_Subtype; subtype Numeric_Subtype_Kinds is Scalar_Subtype_Kinds range A_Signed_Integer_Subtype .. A_Float_Subtype; subtype Discrete_Subtype_Kinds is Scalar_Subtype_Kinds range A_Boolean_Subtype .. A_Modular_Integer_Subtype; subtype Integer_Subtype_Kinds is Numeric_Subtype_Kinds range A_Signed_Integer_Subtype .. A_Modular_Integer_Subtype; subtype Real_Subtype_Kinds is Numeric_Subtype_Kinds range An_Ordinary_Fixed_Subtype .. A_Float_Subtype; subtype Access_Subtype_Kinds is Elementary_Subtype_Kinds range An_Access_To_Object_Subtype .. An_Access_To_Subprogram_Subtype; function Is_Elementary(S : Subtype_View) return Boolean; function Is_Composite(S : Subtype_View) return Boolean; function Is_Scalar(S : Subtype_View) return Boolean; function Is_Numeric(S : Subtype_View) return Boolean; function Is_Discrete(S : Subtype_View) return Boolean; function Is_Integer(S : Subtype_View) return Boolean; function Is_Real(S : Subtype_View) return Boolean; function Is_Access(S : Subtype_View) return Boolean; function Are_Of_Same_Type(Left, Right : Subtype_View) return Boolean; function Is_First_Subtype(S : Subtype_View) return Boolean; function Is_Secondary_Subtype(S : Subtype_View) return Boolean; functino Preconstraint_Subtype(S : Subtype_View) return Subtype_View; function Constraint(S : Subtype_View) return ASIS.Constraint; function First_Subtype(S : Subtype_View) return Subtype_View; function Primitive_Subprograms(S : Subtype_View) return ASIS.Declarative_Item_List; function Is_Formal_Subtype(S : Subtype_View) return Boolean; function Is_Descended_From_Formal_Subtype(S : Subtype_View) return Boolean; type Aspect_Kinds is ( A_Size_Aspect, An_Alignment_Aspect, An_Address_Aspect, A_Position_Aspect, ...); function Is_Aspect_Specified(Aspect : Aspect_Kinds) return Boolean; function Is_Aspect_Directly_Specified(Aspect : Aspect_Kinds) return Boolean; function Is_Static_Subtype(S : Subtype_View) return Boolean; function Is_Constrained(S : Subtype_View) return Boolean; function Is_Statically_Constrained(S : Subtype_View) return Boolean; function Constraint(S : Subtype_View) return ASIS.Constraint; function Are_Statically_Matching(S1, S2 : Subtype_View) return Boolean; function Is_Statically_Compatible(S : Subtype_View; With_Subtype : Subtype_View) return Boolean; function Is_Definite(S : Subtype_View) return Boolean; function Is_Derived_Subtype(S : Subtype_View) return Boolean; function Parent_Subtype(S : Subtype_View) return Subtype_View; function Ultimate_Ancestor(S : Subtype_View) return Subtype_View; function Is_Descendant(S : Subtype_View; Of_Subtype : Subtype_View) return Boolean; function Is_Incomplete_View(S : Subtype_View) return Boolean; function Complete_View(S : Subtype_View) return Subtype_View; function Is_Partial_View(S : Subtype_View) return Boolean; function Full_View(S : Subtype_View) return Subtype_View; function Subtype_Size(S : Subtype_View) return Object_View; function Subtype_Alignment(S : Subtype_View) return Natural; type Elementary_Subtype( Kind : Elementary_Subtype_Kinds := Elementary_Subtype_Kinds'First) is new Subtype_View(Kind); function Is_Universal(E : Elementary_Subtype) return Boolean; type Scalar_Subtype(Kind : Scalar_Kinds := Scalar_Kinds'First) is new Elementary_Subtype(Kind); function Base_Subtype(S : Scalar_Subtype) return Scalar_Subtype; function Low_Bound(S : Scalar_Subtype) return Object_View; function High_Bound(S : Scalar_Subtype) return Object_View; type Access_Subtype( Kind : Access_Subtype_Kinds := Access_Subtype_Kinds'First) is new Elementary_Subtype(Kind); function Is_Anonymous_Access(A : Access_Subtype) return Boolean; function Is_Access_Parameter(A : Access_Subtype) return Boolean; function Is_Access_Result(A : Access_Subtype) return Boolean; function Is_Access_Discriminant(A : Access_Subtype) return Boolean; type Static_Accessibility_Level is new Natural; function Static_Accessibility(A : Access_Subtype) return Static_Accessibility_Level; function Excludes_Null(A : Access_Subtype) return Boolean; function Is_Access_To_Object(A : Access_Subtype) return Boolean; type Access_To_Object_Subtype is new Access_Subtype(An_Access_To_Object_Subtype); function Designated_Subtype(A : Access_To_Object_Subtype) return Subtype_View; function Is_Access_To_Constant(A : Access_To_Object_Subtype) return Boolean; function Is_Pool_Specific(A : Access_To_Object_Subtype) return Boolean; function Storage_Pool(A : Access_To_Object_Subtype) return Object_View; function Storage_Size(A : Access_To_Object_Subtype) return Object_View; function Is_Access_To_Subprogram(A : Access_Subtype) return Boolean; type Access_To_Subprogram_Subtype is new Access_Subtype(An_Access_To_Subprogram_Subtype); function Designated_Profile(A : Access_To_Subprogram_Subtype) return Profile; type Composite_Subtype( Kind : Composite_Subtype_Kinds := Composite_Subtype_Kinds'First) is new Subtype_View(Kind); function Is_Record(C : Composite_Subtype) return Boolean; function Is_Record_Extension(C : Composite_Subtype) return Boolean; function Is_Array(C : Composite_Subtype) return Boolean; type Array_Subtype is new Composite_Subtype(An_Array_Subtype); function Component_Subtype(A : Array_Subtype) return Subtype_View; function Num_Dimensions(A : Array_Subtype) return Positive; function Index_Subtype(A : Array_Subtype; Dimension : Positive := 1) return Discrete_Subtype; function Is_Protected(C : Composite_Subtype) return Boolean; function Is_Task(C : Composite_Subtype) return Boolean; function Is_Limited(C : Composite_Subtype) return Boolean; function Contains_Task(C : Composite_Subtype) return Boolean; function Needs_Finalization(C : Composite_Subtype) return Boolean; function Has_Preelaborable_Initialization(C : Composite_Subtype) return Boolean; function Has_Unknown_Discriminants(C : Composite_Subtype) return Boolean; function Has_Known_Discriminants(C : Composite_Subtype) return Boolean; function Discriminants(C : Composite_Subtype) return Region_Part; function Has_Nondiscriminant_Components(C : Composite_Subtype) return Boolean; function Nondiscriminant_Components(C : Composite_Subtype) return Region_Part; function Is_Tagged(C : Composite_Subtype) return Boolean; type Tagged_Subtype is new Composite_Subtype; type Tagged_Subtype_Array is array(Positive range <>) of Tagged_Subtype; function Is_Classwide(T : Tagged_Subtype) return Boolean; function Root_Subtype(T : Tagged_Subtype) return Tagged_Subtype; function Is_Specific(T : Tagged_Subtype) return Boolean; function Classwide_Subtype(T : Tagged_Subtype) return Tagged_Subtype; function Is_Interface(T : Tagged_Subtype) return Boolean; function Is_Abstract(T : Tagged_Subtype) return Boolean; function Is_Synchronized_Tagged(T : Tagged_Subtype) return Boolean; function Progenitors(T : Tagged_Subtype) return Tagged_Subtype_Array; function External_Tag(T : Tagged_Subtype) return String; ----------------------------------- -- Object Views (Includes "pure" values) ----------------------------------- type Object_View(Kind : Object_View_Kinds := Object_View_Kinds'First) is new View(Kind); function Nominal_Subtype(O : Object_View) return Subtype_View; function Is_Component(O : Object_View) return Boolean; function Enclosing_Object(O : Object_View) return Object_View; function Position(O : Object_View) return Object_View; function Is_Constant(O : Object_View) return Boolean; function Is_Aliased(O : Object_View) return Boolean; function Static_Accessibility(O : Object_View) return Static_Accessibility_Level; function Is_Designated_Object(O : Object_View) return Boolean; function Is_Implicit_Dereference(O : Object_View) return Boolean; function Is_Implicit_Tick_Access(O : Object_View) return Boolean; function Is_Static_Integer(O : Object_View) return Boolean; function Static_Integer_Value(O : Object_View) return Longest_Integer; function Is_Static_Real(O : Object_View) return Boolean; function Static_Real_Value(O : Object_View) return Longest_Float; function Is_Static_String(O : Object_View) return Boolean; function Static_String_Value(O : Object_View) return String; function Static_Wide_String_Value(O : Object_View) return Wide_String; function Static_Wide_Wide_String_Value(O : Object_View) return Wide_Wide_String; function Object_Size(O : Object_View) return Object_View; function Object_Alignment(O : Object_View) return Natural; -------------------------------- -- Parameter and Result Profiles -------------------------------- function Parameters(P : Profile) return Region_Part; function Is_Function(P : Profile) return Boolean; function Result_Subtype(P : Profile) return Subtype_View; function Has_Family_Index(P : Profile) return Boolean; function Family_Index_Subtype(P : Profile) return Subtype_View; function Convention(P : Profile) return Conventions; function Convention_Identifier(P : Profile) return ASIS.Identifier; end ASIS.Object_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Object_Views; use ASIS.Object_Views; package ASIS.Callable_Views is type Callable_View(Kind : Callable_View_Kinds := Callable_View_Kinds'First) is new View(Kind); function Callable_Profile(C : Callable_View) return Profile; function Is_Subprogram(C : Callable_View) return Boolean; function Is_Enumeration_Literal(C : Callable_View) return Boolean; function Is_Entry(C : Callable_View) return Boolean; function Is_Function(C : Callable_View) return Boolean; function Is_Abstract(C : Callable_View) return Boolean; function Is_Null(C : Callable_View) return Boolean; function Is_Primitive(C : Callable_View) return Boolean; function Primitive_On_Subtypes(C : Callable_View) return Subtype_View_List; function Is_Dispatching_Operation(C : Callable_View) return Boolean; function Associated_Tagged_Type(C : Callable_View) return Composite_Subtype; function Is_Prefixed_View(C : Callable_View) return Boolean; function Prefix_Object(C : Callable_View) return Object_View; function Unprefixed_Callable_View(C : Callable_View) return Callable_View; function Is_Designated_Subprogram(C : Callable_View) return Boolean; end ASIS.Callable_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; package ASIS.Package_Views is type Package_View(Kind : Package_View_Kinds := Package_View_Kinds'First) is new Program_Unit(Kind); function Is_Limited_View(P : Package_View) return Boolean; function Full_View(P : Package_View) return Package_View; function Is_Formal_Package(P : Package_View) return Boolean; function Visible_Part(P : Package_View) return Region_Part; end ASIS.Package_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; with ASIS.Callable_Views; with ASIS.Package_Views; package ASIS.Generic_Views is type Generic_View(Kind : Generic_View_kinds := Generic_View_Kinds'First) is new Program_Unit(Kind); function Generic_Formal_Part(G : Generic_View) return Region_Part; function Is_Generic_Package(G : Generic_View) return Boolean; function Current_Package_Instance(G : Generic_View) return Package_Views.Package_View; function Is_Generic_Subprogram(G : Generic_View) return Boolean; function Current_Subprogram_Instance(G : Generic_View) return Callable_Views.Callable_View; end ASIS.Generic_Views; --------------------------------------------------------------- with ASIS.Views; use ASIS.Views; with ASIS.Declared_Views; use ASIS.Declared_Views; package ASIS.Exception_Views is type Exception_View( Kind : Exception_View_Kinds := Exception_View_Kinds'First) is new Declared_View(Kind); function Names_Are_Discarded(E : Exception_View) return Boolean; end ASIS.Exception_Views; Add at end of ASIS.Declarations: function Corresponding_Declared_View( Declaration: in ASIS.Declaration) return ASIS.Declared_Views.Declared_View; Add at end of ASIS.Definitions: function Corresponding_Subtype_View( Type_Definition : in ASIS.Type_Definition) return ASIS.Subtype_Views.Subtype_View; Add at end of ASIS.Expressions: function Corresponding_View( Expression : in ASIS.Expression) return ASIS.Views.View; !discussion --!corrigendum A.18.2(239/2) !ACATS test !appendix From: Robert A. Duff Date: Monday, November 13, 2006 9:00 AM > Here is a first draft of my SI on an ASIS semantic model. Thanks. Sergey Rybin (rybin@adacore.com) should be in on the discussion. **************************************************************** From: Jean-Pierre Rosen Date: Friday, June 9, 2006 1:47 AM Specifications of my thick_queries package: ---------------------------------------------------------------------- -- Thick_Queries - Package specification -- -- Copyright (C) 2002 Adalog -- -- Author: J-P. Rosen -- -- -- -- ADALOG is providing training, consultancy, expertise, -- -- assistance and custom developments in Ada and related software -- -- engineering techniques. For more info about our services: -- -- ADALOG Tel: +33 1 41 24 31 40 -- -- 19-21 rue du 8 mai 1945 Fax: +33 1 41 24 07 36 -- -- 94110 ARCUEIL E-m: info@adalog.fr -- -- FRANCE URL: http://www.adalog.fr -- -- -- -- This unit 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. This unit 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 this program; see file -- -- COPYING. If not, write to the Free Software Foundation, 59 -- -- Temple Place - Suite 330, Boston, MA 02111-1307, 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. -- ---------------------------------------------------------------------- with Asis; with System; package Thick_Queries is ------------------------------------------------------------------------------------------------- -- -- -- Error report -- -- -- ------------------------------------------------------------------------------------------------- type Error_Procedure is access procedure (Message : Wide_String; Elem : Asis.Element); procedure Set_Error_Procedure (To : Error_Procedure); -- Defines a user defined procedure called in case of an internal error -- ("impossible" cases, or calls with inappropriate elements) -- The user procedure may raise an exception. If it doesn't (or no user procedure is defined), -- Program_Error will be raised. ------------------------------------------------------------------------------------------------- -- -- -- Queries about program structure -- -- -- ------------------------------------------------------------------------------------------------- function Enclosing_Program_Unit (Element : Asis.Element; Including_Accept : Boolean := False) return Asis.Defining_Name; -- Return the Defining_Name of the innermost enclosing program unit of any Element -- If Including_Accept is true and the element is within an accept statement, return -- the corresponding entry name from the entry declaration (not really a program unit, -- but useful f.e. if the Element is a Return_Statement, and you want to know what you -- are returning from). -- -- Appropriate Element_Kinds: -- Any element -- -- Returns -- A_Defining_Name -- Nil_Element if Element is a Compilation_Unit -- function Ultimate_Enclosing_Instantiation (The_Element : Asis.Element) return Asis.Declaration; -- For an entity which Is_Part_Of_Instance: -- Return the "true" instantiation, i.e. the one written by the user, going up instantiations -- that appear in generics. function Is_Part_Of_Generic (Declaration : in Asis.Declaration) return Boolean; -- Checks whether the Declaration is included (directly or indirectly) in a generic -- Expected Element: -- A_Declaration ------------------------------------------------------------------------------------------------- -- -- -- Images -- -- -- ------------------------------------------------------------------------------------------------- function Attribute_Name_Image (Attribute : Asis.Expression) return Wide_String; -- Like Pragma_Name_Image, but for an Attribute_Reference -- -- Appropriate Element_Kinds: -- An_Expression -- Appropriate Expression_Kinds: -- An_Attribute_Reference function Extended_Name_Image (Name_Elem : Asis.Element) return Wide_String; -- Image of a name, given either as a simple name or as a Selected_Name function Full_Name_Image (The_Name : in Asis.Element; With_Profile : in Boolean := False) return Wide_String; -- Full name of a name -- Works like Asis.Declarations.Defining_Name_Image (or Name_Image), -- but returns the full (unique) name of The_Name, starting from the -- enclosing compilation unit (Standard for predefined elements). -- If With_Profile is true, "mangles" the name with a profile to provide a name -- that is unique even if overloaded. -- -- Appropriate Element_Kinds: -- A_Defining_Name -- An_Expression -- Appropriate Expression_Kinds: -- An_Identifier -- A_Selected_Component (returns the image of the selector) function Profile_Image (The_Name : Asis.Element; With_Profile : Boolean := True) return Wide_String; -- Image of the profile of a callable construct -- If name is not a callable construct, returns "" -- Otherwise: -- for a procedure, entry...: -- returns '{' { Field). -- - In the case of a renaming whose target is An_Explicit_Dereference, returns Nil_Element -- (the target is statically unknown) -- - In the case of a renaming whose target is A_Function_Call, returns Nil_Element -- (the target is statically unknown, it designates the result of the function call) -- - In the case of the renaming of an attribute, returns the attribute -- Otherwise: returns its argument -- -- In any case, if The_Name is A_Defining_Name, then A_Defining_Name is returned -- if The_Name is An_Identifier, then An_Identifier (or An_Attribute_Reference) is returned -- -- Appropriate Element_Kinds: -- A_Defining_Name -- An_Expression -- Appropriate Expression_Kinds: -- An_Identifier -- A_Selected_Component (operates on selector) -- An_Attribute_Reference function Ultimate_Expression_Type (The_Element : Asis.Expression) return Asis.Definition; -- return the type definition of the ultimate ancestor type of The_Element -- (going up all subtype and derived type declaration). function Expression_Type_Kind (The_Element : Asis.Expression) return Asis.Type_Kinds; -- Real kind of an expression -- return the Type_Kind of the ultimate ancestor of The_Element -- (going up all subtype and derived type declaration). type Expression_Usage_Kinds is (Untouched, Read, Write, Read_Write); function Expression_Usage_Kind (Expr : Asis.Expression) return Expression_Usage_Kinds; -- Returns Untouched if Expr is part of a renaming declaration -- Returns Write if Expr designates a variable which is the -- target of an assignment statement, or an actual corresponding -- to an out parameter in a procedure or entry call. -- Returns Read_Write if Expr designates a variable which is -- an actual corresponding to an in out parameter in a procedure -- or entry call. -- Returns Read in all other cases (including when Expr is not a variable) -- -- Note that this function handles access types properly, i.e. in: -- Integer_Pointer.all := 1; -- if passed Integer_Pointer.all, it will return Write; -- if passed Integer_Pointer, it will return Read. function Includes_Renaming (Path : Asis.Expression) return Boolean; -- Checks whether any element in the Path is a renaming -- -- Appropriate expression kinds: -- An_Identifier -- A_Selected_Component -- A_Function_Call -- An_Indexed_Component -- A_Slice type Pragma_Set is array (Asis.Pragma_Kinds) of Boolean; function Corresponding_Pragma_Set (Element : in Asis.Element) return Pragma_Set; -- Returns the set of pragmas that apply to the corresponding name or defining name -- Note that unlike Corresponding_Pragmas, this query makes sure that the pragma applies -- really to the given element in the case of a multiple declaration. -- -- Appropriate element kinds: -- An_Expression -- A_Defining_Name -- Appropriate expression kinds -- An_Identifier -- A_Selected_Component (function applied to the selector) ------------------------------------------------------------------------------------------------- -- -- -- Queries about callable constructs -- -- -- ------------------------------------------------------------------------------------------------- function Is_Callable_Construct (Element : Asis.Element) return Boolean; -- Checks whether the Element is a callable construct -- Expected elements: -- A_Declaration -- A_Definition -- A_Defining_Name -- An_Expression -- Appropriate Expression_Kinds: -- An_Identifier -- A_Selected_Component (applies to the selector) function Called_Simple_Name (Call : Asis.Element) return Asis.Expression; -- Given a procedure, entry or function call, returns the simple name of the called -- entity (from the call). -- It handles all cases in the same function (i.e. whether it is a procedure or a function, -- whether the call is from an access to subprogram, etc.) -- Returns the simple name of the called entity (i.e. not a Selected_Name). -- For calls to an entry family, returns the name of the family -- Returns a Nil_Element if the call is through an access to subprogram -- Works with dispatching calls! -- -- Appropriate Element_Kinds: -- A_Statement -- An_Expression -- Appropriate Statement_Kinds: -- A_Procedure_Call_Statement -- An_Entry_Call_Statement -- Appropriate Expression_Kinds: -- A_Function_Call function Called_Profile (Call : Asis.Element) return Asis.Parameter_Specification_List; -- Given a procedure, entry or function call, returns the parameter profile of the called -- entity. -- For simple cases, it is like Parameter_Profile (Corresponding_Called_Entity (Call)), -- but it handles all cases in the same function (i.e. whether it is a procedure or a function, -- whether the call is from an access to subprogram, etc.) -- -- Appropriate Element_Kinds: -- A_Statement -- An_Expression -- Appropriate Statement_Kinds: -- A_Procedure_Call_Statement -- An_Entry_Call_Statement -- Appropriate Expression_Kinds: -- A_Function_Call function Formal_Name (Call : Asis.Element; Actual : Asis.List_Index) return Asis.Defining_Name; -- Given a procedure, entry or function call, or a generic instantiation, returns the defining name -- of the formal corresponding to the actual at the given position in the call. -- Note: if the full Parameter_Specification is desired, it is the Enclosing_Element of the Formal_Name -- -- Returns a nil element if: -- Actual is greater than the number of actuals in the call -- The call is to a dispatching operation function Formal_Name (Assoc : Asis.Association) return Asis.Defining_Name; -- Same as above, but retrieves the call (or instantiation) and the position given an association function Actual_Expression (Call : Asis.Element; Formal : Asis.Defining_Name) return Asis.Expression; -- Given a procedure, entry or function call, or a generic instantiation, returns the value -- of the actual corresponding to the formal whose defining_identifier is passed. -- If there is no such actual (the call used the default value), the default expression is returned. -- -- Returns a nil element if: -- The call is to a dispatching operation -- The formal is not from the called entity function Actual_Parameters (Element : Asis.Element; Normalized : Boolean := False) return Asis.Association_List; -- Returns the actual parameters of a procedure, entry, or function call, or of -- a generic instantiation type Type_Attribute is (None, Base, Class); type Profile_Entry is record Is_Access : Boolean; Attribute : Type_Attribute; Name : Asis.Defining_Name; end record; type Profile_Table is array (Asis.List_Index range <>) of Profile_Entry; type Profile_Descriptor (Formals_Length : Asis.ASIS_Natural) is record Result_Type : Profile_Entry; Formals : Profile_Table (1..Formals_Length); end record; function Types_Profile (Declaration : in Asis.Declaration) return Profile_Descriptor; -- Given a callable entity declaration, returns a list of Defining_Name -- First element is the result type for a function, Nil_Element for other callable entities -- Other elements are (in order of declaration) the *types* of the parameters. -- Multiple declarations are separated, i.e. "A,B : Integer" yields two entries in the table. function External_Call_Target (Call : Asis.Element) return Asis.Expression; -- Returns the prefix of the call that designates the target object -- of an external call (LRM 9.5 (2..7)). -- Returns Nil_Element if Element does not designate an external call. -- -- Appropriate Element_Kinds: -- An_Expression -- A_Statement -- -- Appropriate Expression_Kinds: -- A_Function_Call -- -- Appropriate Statement_Kinds: -- A_Procedure_Call_Statement -- An_Entry_Call_Statement -- A_Reqeue_Statement -- A_Requeue_Statement_With_Abort ------------------------------------------------------------------------------------------------- -- -- -- Static evaluator and static properties of ranges and constraints -- -- -- ------------------------------------------------------------------------------------------------- type Biggest_Int is range System.Min_Int .. System.Max_Int; -- The best we can do Non_Static : constant Biggest_Int := -1; subtype Biggest_Natural is Biggest_Int range 0 .. Biggest_Int'Last; subtype Extended_Biggest_Natural is Biggest_Int range Non_Static .. Biggest_Int'Last; type Extended_Biggest_Natural_List is array (Positive range <>) of Extended_Biggest_Natural; function Static_Expression_Value_Image (Expression : Asis.Expression) return Wide_String; -- Computes the value of Expression if it is a static expression -- and represents it as a (wide) string. For enumeration expressions, the -- image of the Pos value of the defining enumeration or character literal -- corresponding to the value of the expression is returned. -- -- For non-static expressions, or expressions that we cannot (yet) evaluate, -- an empty string is returned. -- -- Currently implemented: -- All types: -- Constant -- Parenthesized expression -- 'Pred, 'Succ, 'Pos, 'Val, 'First, 'Last -- Conversions and qualified expressions -- Integer: (provided values are within System.Min_Int .. System.Max_Int) -- Literal -- Named number -- + - * / ** -- Real: -- Literal -- Named number -- Enumerated: -- Literal -- String: (no way to distinguish true "" from non-static expression) -- Literal -- & -- -- Appropriate Element_Kinds: -- An_Expression -- -- The specification of this function is derived (and compatible with) the one -- declared in the GNAT extension ASIS.Extensions -- (except that we do not have the same set of implemented/non-implemented features) function Discrete_Constraining_Bounds (Elem : Asis.Element) return Asis.Element_List; -- Elem must designate a type, a variable, a constant, a formal parameter, -- or a generic formal object. -- -- Returns the expressions that constrain the values of a discrete type. -- Returned list has two elements -- Signed integer type : returns (First_Expression, Last_Expression) -- Subtype of modular : returns (First_Expression, Last_Expression) -- Modular type : returns (Nil_Element, Mod_Expression) -- Enumerated type : returns (First_Defining_Name, Last_Defining_Name) -- -- Returns the bounds that constrain the indexes of an array type. -- Returned list has an even number of elements (First(1), Last (1), First (2), Last (2), ...) -- Each pair of elements is the same as above -- -- Returns Nil_Element_List if the type that applies to Elem is not discrete or array, or is formal -- -- Appropriate Element_Kinds: -- An_Expression -- A_Declaration -- A_Definition -- -- Appropriate Expression_Kind: -- An_Identifier -- A_Selected_Component (operates on the selector) -- A_Function_Call (operates on the returned object) -- -- Appropriate Declaration_Kinds -- An_Ordinary_Type_Declaration -- A_Subtype_Declaration -- A_Task_Type_Declaration -- A_Protected_Type_Declaration -- A_Private_Extension_Declaration -- An_Incomplete_Type_Declaration -- A_Private_Type_Declaration -- A_Variable_Declaration -- A_Constant_Declaration -- A_Component_Declaration -- A_Parameter_Specification -- A_Formal_Object_Declaration -- -- Appropriate Definition_Kinds -- A_Discrete_Range -- A_Constraint -- -- Returns Element_Kind: -- Not_An_Element -- An_Expression -- A_Defining_Name function Discrete_Constraining_Lengths (Elem : Asis.Element) return Extended_Biggest_Natural_List; -- Like Discrete_Constraining_Bounds, but returns the number of values in the range instead of -- the bounds if statically determinable -- Returns Non_Static (-1) if not statically determinable type Result_Confidence is (Unlikely, Possible, Certain); type Variable_Overlap is (Complete, Partial, None); type Proximity is record Confidence : Result_Confidence; Overlap : Variable_Overlap; end record; Same_Variable : constant Proximity := (Certain, Complete); function Variables_Proximity (Left, Right : Asis.Element) return Proximity; -- Determines if Left and Right can possibly refer to (par of) the same variables. -- If Left or Right is not a variable, always returns (Certain, None) -- Overlap => None is only returned with Confidence => Certain -- -- Some especially useful results: -- (Certain, Complete): Statically known to be the same variable -- (Certain, None) : Statically known to be different variables -- -- Appropriate Element_Kinds: -- An_Expression -- A_Defining_Name function Same_Value (Left, Right : Asis.Expression) return Boolean; -- Determines if Left and Right statically have the same value. -- Returns True if: -- Left and Right statically denote the same constant or in parameter -- or Left and Right are discrete and evaluate statically to the same value. end Thick_Queries; **************************************************************** From: Tucker Taft Sent: Sunday, May 13, 2007 3:16 PM Here is an updated SI on a semantic model for ASIS. [This is version /02 of the SI - ED] I have included a package specification and some rationale. I think it is largely complete, but there are many issues to be discussed and interfaces to be reviewed. Enjoy! **************************************************************** From: Tucker Taft Sent: Friday, May 18, 2007 2:53 PM I realize I never specified the interfaces needed to go from an ASIS Element to the "View" type declared in ASIS.Views. Hence, please add the following to the "wording" section for SI99-0024: [This was done in version /03 of the SI - ED] Add at end of ASIS.Declarations: function Corresponding_Declared_View( Declaration: in ASIS.Declaration) return ASIS.Declared_Views.Declared_View; Add at end of ASIS.Definitions: function Corresponding_Subtype_View( Type_Definition : in ASIS.Type_Definition) return ASIS.Subtype_Views.Subtype_View; Add at end of ASIS.Expressions: function Corresponding_View( Expression : in ASIS.Expression) return ASIS.Views.View; **************************************************************** From: Pascal Leroy Sent: Thursday, May 24, 2007 4:48 AM > Here is an updated SI on a semantic model for ASIS. > I have included a package specification and some > rationale. I think it is largely complete, but > there are many issues to be discussed and interfaces > to be reviewed. Enjoy! Is there any reason why you didn't use limited_with_clauses for Typed_Views, rather than lumping 80% of the API in a single package? This seems to be the perfect example where you would want to use them to break circular dependencies. **************************************************************** From: Tucker Taft Sent: Thursday, May 24, 2007 9:21 AM I thought about that, but then realized I would need to use a lot of access parameters, or switch over to using tagged types, and the implications of using access types and/or tagged types seemed pretty bad (see the discussion section of the AI about that). **************************************************************** From: Randy Brukardt Sent: Thursday, May 24, 2007 9:40 PM Tucker writes: > I thought about that, but then realized I would > need to use a lot of access parameters, or switch > over to using tagged types, and the implications > of using access types and/or tagged types seemed > pretty bad (see the discussion section of the > AI about that). Humm, something seems wrong here. I'm on record as believing that (virtually) all new ADTs should be implemented as tagged, controlled types. I hardly ever use anything else these days. I can understand not wanting to require the use of tagged types (although that didn't seem to be a problem for the containers library, and this is similar), but creating an interface which is not *allowed* to be implemented that way is a non-starter for me. Your reason for this decision is described as: > We had various criteria which led to our current proposal of using > a non-tagged hierarchy of discriminated types. One goal was to permit > declaring variables whose underlying entity kind might not be known > at the point of declaration. Similarly, we wanted to be able to manipulate > heterogeneous lists of semantic entities. Both of these precluded > using tagged types, since only class-wide types allow heterogeneity, > and those require explicit initialization. But I don't get it. Surely there is no issue with lists of classwide entities (it's pretty much the only way to build a usefully hetrogeneous list in Ada); if you need a different element, you simply swap one in. And it's easier still if you use an Ada.Containers list. The object is more of an issue, but as I see it the problem is the visible discriminant (a programming style that went out with Ada 83 ;-), not the fact that type is tagged. That is, I think the design should be a bit more like the existing ASIS: type View is tagged private; function View_Kind (V : View) return View_Kinds; If you want compile-time checking, you can always make View an abstract root type, and derive appropriate subtypes: type Subtype_View is new View with private; type Type_View is new View with private; The point is that switching easily between kinds is incompatible with compile-time checking: you can have one or the other, but not both. But perhaps there is a middle ground as I described here: it doesn't seem make a lot of sense to declare objects that can be *any* view; you're more likely to want any kind of subtype, or the like. And you still can declare any view as View'Class; it's just going to require a bit more work on the part of the client (unless they are using an Ada.Container to store these, in which case the container will do all of the work anyway). There is a danger of getting too fancy, of course, but the alternative is an Ada 83 design that has to be implemented with variant records and will be very difficult to implement appropriate memory management (given the difficultly of using controlled types). I'm as guilty as anybody of using these antique designs (I've been using them forever), but seriously: modern programs are built by stitching components together, especially the ones defined in our standards. And extending these types seems like it might be a useful thing to do (so the application can add information to entities, for instance). Surely prefix calls would be useful. So, let's try to use the modern tools along with the old ones. (And a useful side-effect is that we can break up this monolith.) **************************************************************** From: Tucker Taft Sent: Thursday, May 24, 2007 10:28 PM I promise I really tried to use tagged types, and the result was a proliferation of access types. Access types seemed like a real problem because many implementations of ASIS, I believe, will use some kind of software paging scheme, so you can't let the user worry about dangling references. It has to be hidden behind the abstraction. You can certainly use controlled components in the *implementation*, because the basic "View" type is private. However, making it publicly tagged is a real problem, since you couldn't declare a View'class object uninitialized, nor could you declare one as a component of some other type. I think that would be a real hardship. My expectation is that the primary component of the View type will be a controlled object representing an abstract "reference" to a semantic entity. It might have one component that is an access-to-tagged type which would be used as a "cache" of a recently retrieved object, but which could be null, and another that is some kind of unique ID that can work even if the relevant compilation unit is paged out, or not yet loaded in. Of course for an all-in-memory-at-the-same-time implementation, you could just have an access-to-tagged type component and be done with it, but I think that could have scalability issues for large systems. In any case, I don't see the need for a variant record, though it might make sense in some implementations. I suppose another way to think about it is that we have an untagged, discriminated wrapper around an access-to-tagged-type, to offload the storage management issues from the user. Making the discriminants visible provides for run-time checks on conversion, which seems preferable to delaying the checks until the use of some interface. I welcome attempts by others to propose something that works that uses visibly tagged types, but I was not able to come up with anything workable that didn't expose all kinds of storage management issues to the user. If this were my own private interface to my compiler's symbol table, I could probably safely expose a tagged type hierarchy, but since this is supposed to be an interface that acts as a kind of "wrapper" around any implementation's symbol table, I think that is not practical. This is definitely a situation where the devil is in the details, and you really need to work out some examples before you can claim to have a visibly- tagged-type approach that works reasonably. All power to you if you succeed. **************************************************************** From: Tucker Taft Sent: Thursday, May 24, 2007 11:28 PM I seem to be missing a definition of Package_View_Kinds, which should unsurprisingly be: subtype Package_View_Kinds is View_Kinds range A_Noninstance_Package..A_Limited_Package_View; [Added this to version /04 of the SI.] **************************************************************** From: Randy Brukardt Sent: Friday, May 25, 2007 12:05 AM > I promise I really tried to use tagged types, and > the result was a proliferation of access types. > Access types seemed like a real problem because > many implementations of ASIS, I believe, will use > some kind of software paging scheme, so you can't > let the user worry about dangling references. > It has to be hidden behind the abstraction. I surely agree that lots of access types are a problem, but I don't see why there would be *any* visible access types. The only reason we ended up with any in Claw was because copying the objects was too expensive in a few cases (mainly for parent access); you've previously argued that was because the entities in question should have been limited. That argument was reasonable to me. So either these should be limited or there is no problem with access. (How's that for reasoning from no information? ;-) > You can certainly use controlled components in the > *implementation*, because the basic "View" > type is private. However, making it publicly > tagged is a real problem, since you couldn't declare > a View'class object uninitialized, nor could you > declare one as a component of some other type. > I think that would be a real hardship. I can't imagine why; a View by itself (as opposed to one of the subsets of it) seems so broad as to be useless. I guess I'd like to see some sample use cases for this library, because otherwise we're potentially arguing with very different ideas of how this might be used. And that will make a big difference as to the design. Lists of 'class are handled completely by Ada.Containers. So the only possibly problematic case is a singleton View'Class object or component: the question is if that is a realistic use case. > My expectation is that the primary component of > the View type will be a controlled object representing > an abstract "reference" to a semantic entity. ... OK, but there is no reason to hide the taggedness then, and cause issues with lifetime and access to your containing object. (Requiring the use of the Rosen trick is not a good thing, IMHO.) ... > In any case, I don't see the need for a variant > record, though it might make sense in some > implementations. If there is a discriminant, then there ought to be a discriminant-dependent component. Otherwise, you're just violating information hiding for no real reason. (Indeed, I'm unconvinced that there is any use for a visible discriminant...) > I suppose another way to think about it is that > we have an untagged, discriminated wrapper around > an access-to-tagged-type, to offload the storage > management issues from the user. Making the > discriminants visible provides for run-time > checks on conversion, which seems preferable > to delaying the checks until the use of some interface. Huh? In the AI you're talking about *compile-time* checks. That seems like a worthy goal. But now you're talking about *where* run=time checks occur, and that just doesn't seem that important: finding runtime failures requires extensive testing or a fancy tool (kinda like yours...:-), and exactly where those occur doesn't have much effect on whether they are detected. > I welcome attempts by others to propose something > that works that uses visibly tagged types, but I was > not able to come up with anything workable > that didn't expose all kinds of storage management > issues to the user. If this were my own private > interface to my compiler's symbol table, I could > probably safely expose a tagged type hierarchy, > but since this is supposed to be an interface that > acts as a kind of "wrapper" around any implementation's > symbol table, I think that is not practical. I really would like use-cases where storage management issues would be exposed to the user. I can't think of any off-hand, but that's because I don't believe in your Root_Item'Class objects. (Note that I was proposing to keep the common sets as single tagged types, so it wouldn't be necessary to use a 'Class object to declare an object of any Subtype_View, for instance.) But that was all about getting compile-time checking. If you are getting only run-time checks, there is no problem at all: just replace all of your current types with root, concrete tagged types and a query function for the kind. And then you can have all of the objects you want. In all honesty, if it works for your symboltable, it probably will work for most of them (they don't seem that different based on what I've heard at ARG meetings, and yours seems to be among the most complex since it includes its own virtual memory system). I certainly wouldn't want to worry about the implementation details: let the ASIS implementers and potential implementers scream about that if there is a problem. > This is definitely a situation where the devil is > in the details, and you really need to work out some > examples before you can claim to have a visibly- > tagged-type approach that works reasonably. All > power to you if you succeed. I'd like to know what is being lost with my proposal above (if you really have no compile-time checking, and looking at it briefly I didn't see much). Anyway, I'd like to know the use-cases that you have in mind that don't work with that model. Finally, lest I seem too negative here, I realize that this spec required a lot of hard work, and someone had to make an initial proposal. It's lot easier to take potshots at it after the fact, and I'm certainly doing that. I certainly appreciate your work (and am really glad I didn't have to do it!) I realize you might be right that this cannot be a proper O-O design, but I'm trying to figure out why. This problem doesn't seem that different from many other O-O problems; if it can't be done well, then that implies that Ada is inadequate for good O-O design. And it would be valuable to investigate that if true. **************************************************************** From: Pascal Leroy Sent: Friday, May 25, 2007 1:32 AM > I seem to be missing a definition of Package_View_Kinds, > which should unsurprisingly be: > > subtype Package_View_Kinds is View_Kinds range > A_Noninstance_Package..A_Limited_Package_View; Along the same lines, Typed_Views.Are_Of_Same_Type should probably take two parameters. [Added this to version /04 of the SI.] **************************************************************** From: Tucker Taft Sent: Friday, May 25, 2007 12:39 AM Oops. One more (serious) bug. Type View is supposed to have a default for its discriminant. That's pretty critical for all of this to work: type View(Kind : View_Kinds := View_Kinds'First) is private; [Added this to version /04 of the SI.] **************************************************************** From: Pascal Leroy Sent: Friday, May 25, 2007 1:45 AM > You can certainly use controlled components in the > *implementation*, because the basic "View" type is private. Incidentally, why is the discriminant of View not defaulted? Is this an error, or am I missing something? Note that for those types that have a defaulted discriminant, it is not possible for the full type declaration to be a tagged type. This is a bit annoying, as tagged types have many nice properties that untagged types don't have (e.g., equality composes properly). **************************************************************** From: Pascal Leroy Sent: Friday, May 25, 2007 4:33 AM Randy wrote, replying to Tuck: > > Access types seemed like a real problem because > > many implementations of ASIS, I believe, will use > > some kind of software paging scheme, so you can't > > let the user worry about dangling references. > > It has to be hidden behind the abstraction. > > I surely agree that lots of access types are a problem I apologize if I am being thick, but I don't understand why we would have dangling references. Tuck seems to assume that a View is going to map directly to a symbol table entry/tree node. I'm not sure that things would actually work that way. I realize that there are numerous differences between implementations, but in our case a View would certainly *not* be a Diana node. One reason is that the physical layout of a Diana node is very complicated and we wouldn't want to expose that complexity even to the implementation of ASIS. But more importantly, it's very unlikely that the a View would match one-to-one with a Diana node. In all likelihood, a View would contain a pointer to a Diana node with some extra information (possibly other pointers) that would make it possible to retrieve all the properties of the View. We would certainly page the Diana trees in and out (in which case we would record in the View enough information to be able to retrieve the Diana nodes from permanent storage) but we would *not* page the Views themselves. The bottom line is there would be an extra level of indirection at the implementation level, and pointers to Views would remain valid even when Diana trees are paged out. Tuck's dangling reference problem seems like a red herring to me. > I can't imagine why; a View by itself (as opposed to one of > the subsets of > it) seems so broad as to be useless. Maybe, but that's bogus because you surely have the same problem with, say, Subtype_View. > Lists of 'class are handled completely by Ada.Containers. If you believe that access types are a problem, then you have to believe that Ada.Containers would be a problem, too: View'Class could only be used with the indefinite containers, and they are almost certainly implemented with access types. The fact that they are hidden from you doesn't fix any dangling reference problem that might arise. **************************************************************** From: Randy Brukardt Sent: Friday, May 25, 2007 1:43 PM ... > I apologize if I am being thick, but I don't understand why we would have > dangling references. I don't give a flying... sorry need to be polite. I don't care about dangling references; that's not a real problem. My objection to access types in ADT specifications is simply that they force the user to be aware of and usually handle storage management issues. Even when the actual objects are aliased rather than allocated objects. My view is that access types of all sorts should be minimized in all library specifications, preferably to none at all. ... > > I can't imagine why; a View by itself (as opposed to one of > > the subsets of > > it) seems so broad as to be useless. > > Maybe, but that's bogus because you surely have the same problem with, > say, Subtype_View. No, you obviously did not carefully read my proposal. My idea was that Subtype_View would be a tagged concrete type. There would be a query function for the Kind; there would not be any types derived from Subtype_View. So all Subtype_View objects could hold any kind of subtype view, and there would be no need to use 'Class for that. The point of that was to get *real* compile-time checking, such that operations that only make sense for Subtype_Views don't even exist for other types. Tucker's scheme only moves the run-time check to the call site from inside the routine: it is just a very weak precondition. Buys very little IMHO. > > Lists of 'class are handled completely by Ada.Containers. > > If you believe that access types are a problem, then you have to believe > that Ada.Containers would be a problem, too: View'Class could only be used > with the indefinite containers, and they are almost certainly implemented > with access types. The fact that they are hidden from you doesn't fix any > dangling reference problem that might arise. Ada.Containers does the storage management, the user doesn't have to with access types. If the library isn't able to properly manage itself and gets dangling references, it is broken. As I said before, my only concern is about the storage management. If I had time, I'd make a counter-proposal (seems only fair), but I unfortunately won't have time before the meeting. **************************************************************** From: Sergey I. Rybin Sent: Friday, August 10, 2007 11:32 AM I've tried to start my own project aimed at designing the (high level) ASIS semantic model. Things that I do not like in Tucker Taft's proposal are: 1. Tucker's interface is already far too big, and ASIS already has a problem of too big number of queries and other entities that are defined in the ASIS Standard. That's why I've tried to start from a small and observable step. 2. Ada package specifications in the Tucker's proposal do not contain any documentation at all. There are two reasons why I definitely do not like this. - devil is in the details, when you are writing the documentation, you *have* to think about details, so undocumented specs contain too much of devil; - I do remember how much time it took to finalize all the documentation for ASIS 95, so, if we start from such a huge, but completely undocumented spec, we have all the chances that it will never be completed (as a part of any further ASIS standard) That's why I've tried to start with fully documented specifications 3. Tucker's specs are not compilable. I'm going to keep my specs fully compilable from the very beginning of the project. 4. There is no usage example in the Tucker's proposal. I've tried to provide at least a couple of simple examples. 5. Tucker's proposal looks very hard from the implementer's viewpoint, and it is not easy to select a relatively closed and useful subset to start from. I've tried to provide a practically mplementable start (I think I would need no more then a week to implement what I'm suggesting here), and to use an easily extendable set of packages. From the other side, Tucker's proposal is far more complete and covers all the language and most of the semantic needs we could imagine at the application side, and my project in its current state provides only a very basic scheme and a couple of really useful queries. The main open issues in my project are: 1. Basic abstractions. I have some strong feeling that we need both Views (on Entities) and Entities. Ticker's proposal is based on Views only. At the moment I cannot provide any proof or justification for the need of both Entities and Views. 2. Classification. At the moment I cannot say in what extent enumeration types should be used to classify views and entities. In the current spec all the base types are not tagged, but most probably I will move to the object oriented classification of the Ada entities without using enumeration types. I'm very far from suggesting that my specs should replace Tucker's proposal as a means to bridge the gap between low level ASIS queries and high level semantic needs at the application side. This is just a part of the discussion... ----- package Asis.Entities is -- This package defines the main abstractions for the new ASIS semantic -- interface. type Entity is private; -- type Entity is tagged private; ??? -- Represents an entity. The meaning of the notion "Entity" is defined by -- the Ada Standard Nil_Entity : constant Entity; -- Represents nothing Standard_Entity : constant Entity; -- Represents the predefined package Standard ASIS_Inappropriate_Entity : exception; -- Is raised if a given Entity value cannot be used as an argument for a -- given query type Entity_List is array (Natural range <>) of Entity; -- The most trivial solution! Most probably, we have to switch to -- containers here (ordered sets?) function Is_Equal (Left : Entity; Right : Entity) return Boolean; -- Returns True if Left and Right represents the same Entity, and False -- otherwise -- ??? Do we need Is_Identical, and do we have to bother about queries for -- ??? processing more then one Context at a time? function ">" (Left : Entity; Right : Entity) return Boolean; -- This function can be used to define ordered containers for Entity -- values. This ">" does not have any reasonable "physical" meaning function Is_Nil (Left : Entity) return Boolean; -- Check if the argument represents nothing function Is_Scope (E : Entity) return Boolean; -- Some entities are scopes (that is, they may contain other entities as -- subcomponents, e.g. a package entity or a protected type entity). The -- meaning of the notion "scope" should be as close to Ada Standard as -- possible type View is -- Various kinds of views a context or a client may have on an entity (Not_A_View, Full_View, -- All the entity properties are available. All the non-nil Entities -- have full view. -- For packages: Client_View, Child_To_Parent_View, -- For library packages Limited_Library_View, Private_Library_View, Limited_Private_Library_View, -- For types Incomplete_View, Private_View, -- For renamable entities Renamed_View -- anything else??? ); type View_On_Entity is private; -- type View_On_Entity is tagged private; ??? -- type View_On_Entity is new Entity with private; ??? -- Represents a specific view on a specific entity Nil_View_On_Entity : constant View_On_Entity; ASIS_Inappropriate_View : exception; -- Is raised when a given view cannot be applied to a given entity (for -- example, we cannot view a package with Incomplete_View type View_On_Entity_List is array (Natural range <>) of View_On_Entity; -- The most trivial solution! Most probably, we have to switch to -- containers here (ordered sets?) function Is_Nil (Left : View_On_Entity) return Boolean; -- Check if the argument represents nothing function Is_Equal (Left : View_On_Entity; Right : View_On_Entity) return Boolean; -- Returns True if Left and Right represents the same view on the same -- Entity, and False otherwise function ">" (Left : View_On_Entity; Right : View_On_Entity) return Boolean; -- This function can be used to define ordered containers for -- View_On_Entity values. This ">" does not have any reasonable "physical" -- meaning function Represented_Entity (Viewed_Entity : View_On_Entity) return Entity; function Represented_View (Viewed_Entity : View_On_Entity) return View; function Get_View (On_Entity : Entity; View_As : View) return View_On_Entity; -- Returns the desired view at the argument entity. Raises -- ASIS_Inappropriate_View if the given view cannot be applied to the -- argument entity procedure Change_View (Viewed_Entity : in out View_On_Entity; To_View : View); -- Changes the view to the argument entity. Raises ASIS_Inappropriate_View -- if the given view cannot be applied to the argument entity private -- Just a placeholder for the moment type Entity is new Element; Nil_Entity : constant Entity := Entity (Nil_Element); type View_On_Entity is new Entity; Nil_View_On_Entity : constant View_On_Entity := View_On_Entity (Nil_Entity); end Asis.Entities; ----- package Asis.Entities.Structure is -- This package defines bridges between core Asis abstractions and -- Entities. -- This package also defines the structural queries for the high-level -- semantic abstractions. A program is viwed as a hierarchy of scopes. Each -- scope may contain other scopes and entities that are not scopes. This -- gives the possibility to decompose and to traverse the semantic -- structure of the program -------------------------------------- -- Asis.Compilation_Unit <-> Entity -- -------------------------------------- function CU_Entity (CU : Asis.Compilation_Unit) return Entity; -- Returns the entity defined by the argumentg compilation unit. -- -- Appropriate Unit_Kinds: -- A_Procedure -- A_Function -- A_Package -- A_Generic_Procedure -- A_Generic_Function -- A_Generic_Package -- A_Procedure_Instance -- A_Function_Instance -- A_Package_Instance -- A_Procedure_Renaming -- A_Function_Renaming -- A_Package_Renaming -- A_Generic_Procedure_Renaming -- A_Generic_Function_Renaming -- A_Generic_Package_Renaming -- A_Procedure_Body -- A_Function_Body -- A_Package_Body -- A_Procedure_Body_Subunit -- A_Function_Body_Subunit -- A_Package_Body_Subunit -- A_Task_Body_Subunit -- A_Protected_Body_Subunit function Enclosing_Unit (E : Entity) return Asis.Compilation_Unit; -- Returns ASIS Comnpilation Unit where the given entity is declared. -- Raises ASIS_Inappropriate_Entity if Is_Nil (E). ------------------------------- -- Asis.Element <-> Entity -- ------------------------------- function Represented_Entity (E : Asis.Element) return Entity; -- If the argument Element represents some entity (or some view on this -- entity), returns the corresponding entity, Otherwise returns Nil_Entity. -- -- More then one Element can represent the same Entity. For example, -- if a given procedure has a separate declaration completed by a body -- stub, then the corresponding A_Procedure_Declaration, -- A_Procedure_Body_Stub and A_Procedure_Body_Declaration Elements all -- represent the same procedure entity. function Represented_View (E : Asis.Element) return View_On_Entity; -- If the argument Element represents a particular view on some Entity, -- returns this view (e.g, A_Private_Type_Declaration Element represents -- Private_View on a type Entity. If a represented Entity does not have -- any other views except Full_View, returns the full view. If the argument -- Element does not represent any Entity, returns Nil_View_On_Entity. function Representing_Element (E : Entity) return Asis.Element; -- Returns the elemengt that declares (or defines, in case of anonymous -- entity) the argument entity. -- -- If an argument Entity is a named entity (that is, it corresponds to some -- declaration according to the Ada Standard, then this query returns the -- corresponding A_Defining_Name Element. If an argument Entity is -- anonymous, then the query returns A_Definition Element that defines the -- entity (e,g, A_Subtype_Definition is returned for an anonymous subtype). -- -- Nil_Element is returned for Nil_Entity -- -- ??? Precise descrription of all possible cases is needed. -- -- ??? Do we need similar query for View_On_Entity??? function Is_Anonymous (E : Entity) return Boolean; -- Checks if the Entity is an anonymois entity, that is, has no defining -- name associated with it. Returns True for Nil_Entity. ------------------------------ -- Basic structural queries -- ------------------------------ -- If an Entity is a scope (that is, Asis.Entities.Is_Scope returns True -- for it), it contains other entities, These entities can be obtained -- from it. Some of these entities also are Is_Scope, and, therefore, -- can be further decomposed. type Filter_Access is access function (E : Entity) return Boolean; -- Pointer to Entity filters. An Entity filter is a boolean function that -- has an entity as its only parameter. Filters can be used when obtaining -- entities from scopes to get only those entities that are of interest -- for further analysis. function No_Filter (E : Entity) return Boolean; -- Always returns True function Enclosed_Entities (Scope_Entity : Entity; Viewed_As : View := Full_View; Include_Implicit : Boolean := False; Use_Filter : Filter_Access := No_Filter'Access) return Entity_List; -- Requires Is_Scope (Scope_Entity), and raises ASIS_Inappropriate_Entity -- otherwise. Returns the list of the entities declared in Scope_Entity. -- All the other parameters define various ways to filter out entities to -- be includes in the result list. Include_Implicit indicates if implicitly -- declared entities should be included in the result. Only those entities -- for that Use_Filter returns true are included in the result (this gives -- the possibility to return, for example, all the subprograms defined in a -- given package). function Enclosed_Views (Scope_Entity : Entity; Viewed_As : View := Full_View; Include_Implicit : Boolean := False; Use_Filter : Filter_Access := No_Filter'Access) return View_On_Entity_List; -- Similar to Enclosed_Entities, but returns views on entities. function Enclosing_Scope (E : Entity) return Entity; -- Returns the scope Entity where the argument Entity is derfined. Returns -- Standard_Entity in case if the argument is a library-level entity. -- Returns Nil_ENtity in case if the argument is Standard_Entity. Rasies -- ASIS_Inappropriate_Entity if the argument is Nil_Entity -- Do we need the following queries: -- function Enclosing_Scope (E : View_On_Entity) return Entity; -- function Enclosing_Scope (E : Entity) return View_On_Entity; -- function Enclosing_Scope (E : View_On_Entity) return View_On_Entity; -- ??? end Asis.Entities.Structure; ---- package Asis.Entities.Structure.Traversing is -- This package defines the generic traversal procedure Traverse_Scope that -- allows an ASIS application to traverse recursively a piece of an Ada -- code viewed as a hierarchy of scope entities, Traverse_Scope is in -- some way similar to the syntactical traversing procedure -- Asis.Iterator.Traverse_Element, but it traverses not the syntax -- structure, but the hierarchy of logically nested entities. generic type State_Information is limited private; with procedure Pre_Operation (E : Entity; Control : in out Traverse_Control; State : in out State_Information) is <>; with procedure Post_Operation (E : Entity; Control : in out Traverse_Control; State : in out State_Information) is <>; procedure Traverse_Entity (E : Entity; Control : in out Traverse_Control; State : in out State_Information); -- E - Specifies the initial Entity in the traversal -- Control - Specifies what next to do with the traversal -- State_Information - Specifies other information for the traversal -- -- Traverses the entity and all the entities defined in it if the entity is -- a sope entity. -- -- If a scope entity contains one or more entities defined in it, each of -- these entities is called a child entity. An entity's parent (scope) -- entity is its Enclosing_Scope. Children with the same parent are -- sibling entitues. The type Traverse_Control uses the terms children and -- siblings to control the traverse. -- -- For each entity, the formal procedure Pre_Operation is called when first -- visiting the entity. Each of that entity's children are then visited -- and finally the formal procedure Post_Operation is called for the -- entity. -- -- The order of entity traversal is in terms of the logical ordering of -- the entities in the enclosing scope entity. Entities are traversed in -- left-to-right and top-to-bottom order. -- -- Traversal of Implicit entities: ??? -- -- Traversal can be controlled with the Control parameter. -- -- A call to an instance of Traverse_Entity will not result in calls to -- Pre_Operation or Post_Operation unless Control is set to Continue. -- -- The subprograms matching Pre_Operation and Post_Operation can set -- their Control parameter to affect the traverse: -- -- Continue -- Continues the normal depth-first -- -- traversal. -- -- Abandon_Children -- Prevents traversal of the current entity's -- -- children. -- -- If set in a Pre_Operation, traversal picks -- -- up with the next sibling entity of the -- -- current scope entity. -- -- If set in a Post_Operation, this is the -- -- same as Continue, all children will -- -- already have been traversed. Traversal -- -- picks up with the Post_Operation of the -- -- parent. -- -- Abandon_Siblings -- Prevents traversal of the current entity's -- -- children and remaining siblings. -- -- If set in a Pre_Operation, this abandons -- -- the associated Post_Operation for the -- -- current entity. Traversal picks up with -- -- the Post_Operation of the parent. -- -- If set in a Post_Operation, traversal -- -- picks up with the Post_Operation of the -- -- parent. -- -- Terminate_Immediately -- Does exactly that. -- -- Raises ASIS_Inappropriate_Entity if the entity is a Nil_Entity -- -- ??? More possibilities to control traversal? -- ??? - filters -- ??? - specify views on scopes being traversed? end Asis.Entities.Structure.Traversing; ---- -- Core ASIS: with Asis; use Asis; -- ASIS Semantic Interface: with Asis.Entities; package Asis_Semantic_Level_Usage_Examples is -- This package contains usage examples for the proposed high-level ASIS -- sematic interface. -- -- Because in its current stage the ASIS semantic interface provides only -- very basic possibilities, all the example routines in this package -- operates on ASIS Elements. The usege of the new queries is demonstrated -- in the implementations of these queries. function Get_All_Subprograms (Scope_Element : Asis.Element) return Asis.Element_List; -- If the argument Element corresponds to a scope entity, returns a list -- of subprograms declared in this scope. Otherwise returns Nil_Element. -- For each subprogram being returned, the first Element defining this -- subproram is included in the result list (that is, if a subprogram -- has a separate spec, A_Procedure_Declaration or A_Function_Declaration -- Element is returned, if there is no separate spec - either a subprogram -- body stub or a subprogram body declaration element is returned. procedure Print_All_Declared_Entities (Scope_Element : Asis.Element); -- If the argument Element corresponds to a scope entity, prints out -- defining names of all the entities explicitly declared in this scope. end Asis_Semantic_Level_Usage_Examples; ----- with Ada.Wide_Text_IO; -- Core ASIS: with Asis.Declarations; with Asis.Elements; -- ASIS Semantic Interface: with Asis.Entities.Structure; with Asis.Entities.Structure.Traversing; package body Asis_Semantic_Level_Usage_Examples is ----------------------- -- Local subprograms -- ----------------------- function Only_Subprograms (E : Asis.Entities.Entity) return Boolean; -- Returns True only for subprogram entities. ------------------------- -- Get_All_Subprograms -- ------------------------- function Get_All_Subprograms (Scope_Element : Asis.Element) return Asis.Element_List is Arg_Scope : constant Asis.Entities.Entity := Asis.Entities.Structure.Represented_Entity (Scope_Element); begin if Asis.Entities.Is_Scope (Arg_Scope) then declare Result_Entities : constant Asis.Entities.Entity_List := Asis.Entities.Structure.Enclosed_Entities (Scope_Entity => Arg_Scope, Use_Filter => Only_Subprograms'Access); Result_Elements : Asis.Element_List (Result_Entities'Range); begin for J in Result_Elements'Range loop Result_Elements (J) := Asis.Entities.Structure.Representing_Element (Result_Entities (J)); end loop; return Result_Elements; end; else return Asis.Nil_Element_List; end if; end Get_All_Subprograms; ---------------------- -- Only_Subprograms -- ---------------------- function Only_Subprograms (E : Asis.Entities.Entity) return Boolean is Tmp_El : constant Asis.Element := Asis.Entities.Structure.Representing_Element (E); Result : Boolean := False; begin case Asis.Elements.Declaration_Kind (Tmp_El) is when A_Procedure_Declaration | A_Function_Declaration | A_Procedure_Body_Declaration | A_Function_Body_Declaration | A_Procedure_Body_Stub | A_Function_Body_Stub | A_Procedure_Instantiation | A_Function_Instantiation => Result := True; when others => null; end case; return Result; end Only_Subprograms; --------------------------------- -- Print_All_Declared_Entities -- --------------------------------- procedure Print_All_Declared_Entities (Scope_Element : Asis.Element) is Arg_Scope : constant Asis.Entities.Entity := Asis.Entities.Structure.Represented_Entity (Scope_Element); type My_State is (Not_Used); procedure Pre_Operation (E : Asis.Entities.Entity; Control : in out Traverse_Control; State : in out My_State); -- If an E does have a defining name, prints out it String image. Does -- nothing if Is_Anonymous (E); procedure Post_Operation (E : Asis.Entities.Entity; Control : in out Traverse_Control; State : in out My_State); -- Does nothing procedure Print_Defining_Names is new Asis.Entities.Structure.Traversing.Traverse_Entity (My_State); My_Traversal_State : My_State := Not_Used; My_Traversal_Control : Asis.Traverse_Control := Asis.Continue; procedure Pre_Operation (E : Asis.Entities.Entity; Control : in out Traverse_Control; State : in out My_State) is Tmp_El : Asis.Element; begin if not Asis.Entities.Structure.Is_Anonymous (E) then Tmp_El := Asis.Entities.Structure.Representing_Element (E); Ada.Wide_Text_IO.Put_Line (Asis.Declarations.Defining_Name_Image (Tmp_El)); end if; end Pre_Operation; procedure Post_Operation (E : Asis.Entities.Entity; Control : in out Traverse_Control; State : in out My_State) is begin null; end Post_Operation; begin -- Print_All_Declared_Entities if not Asis.Entities.Is_Nil (Arg_Scope) then Print_Defining_Names (Arg_Scope, My_Traversal_Control, My_Traversal_State); end if; end Print_All_Declared_Entities; end Asis_Semantic_Level_Usage_Examples; **************************************************************** From: Tucker Taft Sent: Wednesday, October 3, 2007 2:01 PM I have attached an update to SI-24 [This is version /06 - ED.], providing an ASIS semantic model. The major change is that I created a tagged-type version. It uses interfaces heavily, but I didn't have to use "limited with." It presumes the existence of a singleton "holder" container type, which I illustrated in an earlier note. I have attached a slightly updated version of that as well. I haven't had the time to create any examples of use, which could be very telling. Be that as it may, hopefully this will provide some indication of the possibilities. The tagged type version does look cleaner. The package structure is: ASIS.Views ASIS.Declared_Views ASIS.Subtype_Views ASIS.Object_Views ASIS.Profiles ASIS.Subtype_Views.Elementary ASIS.Subtype_Views.Composite ASIS.Callable_Views ASIS.Package_Views ASIS.Generic_Views ASIS.Exception_Views Here is one issue with the tagged-type version, as mentioned in the !discussion section: ---- IMPLEMENTATION IN ADA 95 An Ada 95 version of this would be somewhat harder. Clearly all of the interface types would become "regular" abstract tagged types. However, there is a subtle issue with Declared_Views, since a given type descended from Object_View might or might not want to be a descendant of Declared_View, and that kind of thing implies multiple inheritance. The same goes for Subtype_View and Callable_View. To avoid this problem, we could have a separate type that captures the information associated with a Declared_View, perhaps call it "View_Declaration," and allow any View to have one. That way we wouldn't be depending on multiple inheritance. View_Declaration might be a plain old private type, which would be consistent with the types Region_Part and Declarative_Region used already. -------- Any comments on the above would be appreciated. I am tempted to make the above change, so that most of this can be prototyped in "pure" Ada 95. Declared_Views are a bit confusing the way they are currently connected into the hierarchy. ****************************************************************