-- ============================================================================ -- >>>>>>>>>>>>>>>>>>>>>>>>>> ADA COMPILATION UNIT <<<<<<<<<<<<<<<<<<<<<<<<<<<< -- ============================================================================ -- -- NAME: Region_View -- -- SPECIFICATION -- -- AUTHOR: Chuck Hobin -- General Research Corporation -- -- CHANGE HISTORY -- -- MM-DD-YY | Initials | Description -- ---------------------------------------------------------------------------- -- -- ============================================================================ -- -- -- +=========================================================================+ -- | | -- | REGION_VIEW - an Asis abstraction | -- | | -- | This package provides the operations to construct and manage the | -- | region view of a library unit. The view is the hierarchy of | -- | declarative regions which define the scope of declarations in the | -- | unit. | -- | | -- +=========================================================================+ -- -- -- INTRODUCTION -- -- Ada specifies the rules of declaration scope and visibility using the -- concept of a "declarative region". A declarative region (LRM 8.1) is a -- logical portion of program text that bounds the scope of declarations. -- Regions can be nested within other regions, thus forming a hierarchy. -- A declaration's scope extends from the point of declaration to the end -- of the declarative region that immediately contains it. For certain -- forms of declaration, such as those occurring in the visible part of -- a package declaration, the scope also extends into the enclosing region. -- -- The declarative region hierarchy is a useful structure for static code -- analysis. Possible applications include: -- -- * Documenting the internal structure of a library unit. -- * Constructing a hierarchical symbol table (by creating a Namespace view -- for each region). -- * Distinguishing local vs. global symbol references in a program unit. -- * Determining the set of declarations declared by a library unit that -- are visible outside the unit. -- -- Access functions for the region hierarchy are not provided by ASIS. -- This package exports operations for constructing a "region view", -- a concrete representation of the declarative region hierarchy, -- via an ASIS element traversal. -- -- -- ORGANIZATION OF THE VIEW -- -- A declarative region is a logical, not a physical, concept. Regions -- formed by program units may span multiple compilation units. For -- example, the region for a package can include a package declaration, -- a package body stub, and the proper body, each of which may reside -- in a different compilation unit. A region view is therefore a view of -- a "logical" library unit, i.e., a physical library unit together with -- its corresponding secondary units (body and subunits), if any. We -- refer to this collection of compilation units as a Library Unit Group -- (LUG). -- -- We have found it useful to define a physical counterpart for the -- declarative region; we call this a "region part". We define a region part -- to be a physical, contiguous text fragment, residing in a single -- compilation unit, that is a distinct part of one declarative region. A -- declarative region contains one or more non-overlapping region parts which, -- taken together, comprise the entire text of the region. -- -- An Ada compilation unit can be viewed as hierarchy of region parts. The -- structure of this hierarchy is directly related to the corresponding -- hierarchy of the logical declarative regions. The region parts effectively -- partition the structural ASIS elements of the unit, i.e., each element is -- associated with a single region part. We rely on this property as we -- build the view. The support package Region_Support, which implements a -- mapping between ASIS elements and region parts, describes this concept in -- further detail. -- -- A region view is constructed from the compilation units comprising a -- LUG. The view contains: -- -- * the declarative region hierarchy for the LUG as a whole, and -- -- * the region part hierarchy for each compilation unit in the LUG. -- -- It is possible to traverse back and forth between the declarative region -- and region part hierarchies. Each declarative region contains pointers -- to its constituent region parts. Conversely, given a region part, one -- can locate the declarative region that contains it. -- -- The data structures used to represent the view are located in package -- Region_View_Structures. -- -- -- VIEW CONSTRUCTION REQUIREMENTS -- -- The view is constructed by a traversal of the structural ASIS elements -- comprising each compilation unit in the LUG. For the view to be constructed -- correctly, certain requirements are imposed on this traversal. -- -- * REQUIREMENT #1 -- -- The compilation units of the LUG must be analyzed in dependency -- order. -- -- This means that a library unit body must be traversed after its -- corresponding spec; likewise, a subunit can be traversed only after all -- of its ancestor units have been traversed. -- -- Second, because the operations of this package use ASIS semantic -- queries: -- -- * REQUIREMENT #2 -- -- All of the compilation units must be consistent (i.e., not obsolete) -- in the library. -- -- Certain applications may wish to use the partially constructed view -- while the traversal is taking place. For example, one might want to -- know if the traversal is currently in a subprogram that is visible outside -- the LUG. This fact could be determined by 1) locating the -- declarative region containing the innermost region part being traversed -- and 2) examining the context of the region in the declarative region -- hierarchy. -- -- To permit this kind of application, there are two additional requirements: -- -- * REQUIREMENT #3 -- -- The elements of compilation unit must be traversed in a top-to-bottom, -- left-to-right (i.e., source code) order. -- -- Note that this is the traversal order of the generic procedure -- Asis.Elements.Traverse_Element. -- -- * REQUIREMENT #4 -- -- The traversal must notify this package 1) when it starts and finishes -- each compilation unit and 2) when it enters and leaves each region part -- within a compilation unit. -- -- This package provides an operation for each of these events. As a side -- effect, the operations add information to the view. -- -- -- USING THE PACKAGE OPERATIONS -- -- This package does *not* perform the actual ASIS element traversal; the -- traversal must be implemented by another unit which calls the operations -- of this package at the appropriate times. We chose this division so -- that construction of a region view could be incorporated into a -- traversal that also collects other information. -- -- (A sample driver that uses Asis.Elements.Traverse_Element to perform -- a basic traversal has been provided - see unit Build_Region_View.) -- -- Given that a LUG has been selected for analysis, and all of its compilation -- units are known to be consistent in the library, the following steps -- construct a region view for the LUG. -- -- 1. Initialize the view data structure, which is an object of the type -- Region_View_Structures.Region_View. -- -- Region_View.Initialize( The_View ); -- -- 2. Traverse the elements of each compilation unit in the LUG. (Remember -- to analyze the units in dependency order.) Before traversing a -- given unit, notify this package: -- -- Region_View.Start_Comp_Unit( The_Unit, The_View ); -- -- By convention, the outermost region part for a comp unit is a -- special region part with kind 'A_Compilation_Unit'. To create -- this, the following code fragment should immediately follow the -- call to Start_Comp_Unit: -- -- Comp_Unit_Region := Region_Support.Equivalent_Region (The_Unit); -- Region_View.Enter_Region (Comp_Unit_Region, The_View); -- -- Also notify this package when the traversal of the unit is finished: -- -- Region_View.Leave_Region (Comp_Unit_Region, The_View); -- Region_View.Finish_Comp_Unit( The_Unit, The_View ); -- -- 3. As the traversal of a comp unit visits the elements, it must notify -- this package when it enters a region part and when it leaves the part. -- At any given time, the traversal is inside zero or more nested region -- parts, and the first one to be left is always the last one entered. -- -- The package Region_Support identifies elements that denote one or -- more region parts. Such an element is called the "head element" of -- of the part. For each part, Region_Support identifies the subelements -- of the head element that comprise the part. -- -- When an element denoting one or more region parts is encountered, -- each region part needs to be identified to this package. The traversal -- then continues on, visiting the elements inside each part. The -- following code fragment, which uses the operations of Region_Support, -- demonstrates how this is done: -- -- if Region_Support.Denotes_One_Or_More_Regions (The_Element) then -- declare -- Region_List : constant Region_Support.Region_List := -- Region_Support.Denoted_Regions (The_Element); -- begin -- -- Consider each region part denoted by The_Element. -- for I in Region_List'Range loop -- declare -- Subelements : constant Asis.Element_List := -- Region_Support.Subelements (Region_List (I)); -- begin -- Region_View.Enter_Region (Region_List (I), The_View); -- for J in Subelements'Range loop -- -- Recursively traverse each subelement. -- end loop; -- Region_View.Leave_Region (Region_List (I), The_View); -- end; -- end loop; -- end; -- end if; -- ------------------------------------------------------------------------------- with Asis; with Region_View_Structures; with Region_Support; package Region_View is procedure Initialize (The_View : in out Region_View_Structures.Region_View); -- Initialize creates a new region view. The following operations update -- the view as the compilation units and elements of a LUG are traversed. procedure Start_Comp_Unit (The_Unit : Asis.Compilation_Unit; View_To_Update : in out Region_View_Structures.Region_View); procedure Enter_Region (The_Region : Region_Support.Region; View_To_Update : in out Region_View_Structures.Region_View); procedure Leave_Region (The_Region : Region_Support.Region; View_To_Update : in out Region_View_Structures.Region_View); procedure Finish_Comp_Unit (The_Unit : Asis.Compilation_Unit; View_To_Update : in out Region_View_Structures.Region_View); procedure Free (The_View : in out Region_View_Structures.Region_View); -- Free releases all storage occupied by a region view. end Region_View;