10.1. Compilation Units - Library Units

[UP][NEXT]

The text of a program can be submitted to the compiler in one or more compilations. Each compilation is a succession of compilation units.

    compilation ::= {compilation_unit} 

    compilation_unit ::=
         context_clause library_unit | context_clause secondary_unit 

    library_unit ::=
         subprogram_declaration | package_declaration
       | generic_declaration    | generic_instantiation
       | subprogram_body 

    secondary_unit ::= library_unit_body | subunit 

    library_unit_body ::= subprogram_body | package_body 

The compilation units of a program are said to belong to a program library. A compilation unit defines either a library unit or a secondary unit. A secondary unit is either the separately compiled proper body of a library unit, or a subunit of another compilation unit. The designator of a separately compiled subprogram (whether a library unit or a subunit) must be an identifier. Within a program library the simple names of all library units must be distinct identifiers.

The effect of compiling a library unit is to define (or redefine) this unit as one that belongs to the program library. For the visibility rules, each library unit acts as a declaration that occurs immediately within the package STANDARD.

The effect of compiling a secondary unit is to define the body of a library unit, or in the case of a subunit, to define the proper body of a program unit that is declared within another compilation unit.

A subprogram body given in a compilation unit is interpreted as a secondary unit if the program library already contains a library unit that is a subprogram with the same name; it is otherwise interpreted both as a library unit and as the corresponding library unit body (that is, as a secondary unit).

The compilation units of a compilation are compiled in the given order. A pragma that applies to the whole of a compilation must appear before the first compilation unit of that compilation.

A subprogram that is a library unit can be used as a main program in the usual sense. Each main program acts as if called by some environment task; the means by which this execution is initiated are not prescribed by the language definition. An implementation may impose certain requirements on the parameters and on the result, if any, of a main program (these requirements must be stated in Appendix F). In any case, every implementation is required to allow, at least, main programs that are parameterless procedures, and every main program must be a subprogram that is a library unit.

Notes:

A simple program may consist of a single compilation unit. A compilation need not have any compilation units; for example, its text can consist of pragmas.

The designator of a library function cannot be an operator symbol, but a renaming declaration is allowed to rename a library function as an operator. Two library subprograms must have distinct simple names and hence cannot overload each other. However, renaming declarations are allowed to define overloaded names for such subprograms, and a locally declared subprogram is allowed to overload a library subprogram. The expanded name STANDARD.L can be used for a library unit L (unless the name STANDARD is hidden) since library units act as declarations that occur immediately within the package STANDARD.

References: allow, context clause, declaration, designator, environment, generic declaration, generic instantiation, hiding, identifier, library unit, local declaration, must, name, occur immediately within, operator, operator symbol, overloading, and 8.7, package body, package declaration, parameter of a subprogram, pragma, procedure, program unit, proper body, renaming declaration, simple name, standard package, subprogram, subprogram body, subprogram declaration, subunit, task, visibility.

Sub-topics:

10.1.1. Context Clauses - With Clauses

[UP][NEXT]

A context clause is used to specify the library units whose names are needed within a compilation unit.

    context_clause ::= {with_clause {use_clause}} 

    with_clause ::= with unit_simple_name {, unit_simple_name}; 

The names that appear in a context clause must be the simple names of library units. The simple name of any library unit is allowed within a with clause. The only names allowed in a use clause of a context clause are the simple names of library packages mentioned by previous with clauses of the context clause. A simple name declared by a renaming declaration is not allowed in a context clause.

The with clauses and use clauses of the context clause of a library unit apply to this library unit and also to the secondary unit that defines the corresponding body (whether such a clause is repeated or not for this unit). Similarly, the with clauses and use clauses of the context clause of a compilation unit apply to this unit and also to its subunits, if any.

If a library unit is named by a with clause that applies to a compilation unit, then this library unit is directly visible within the compilation unit, except where hidden; the library unit is visible as if declared immediately within the package STANDARD (see 8.6).

Dependences among compilation units are defined by with clauses; that is, a compilation unit that mentions other library units in its with clauses depends on those library units. These dependences between units are taken into account for the determination of the allowed order of compilation (and recompilation) of compilation units, as explained in section 10.3, and for the determination of the allowed order of elaboration of compilation units, as explained in section 10.5.

Notes:

A library unit named by a with clause of a compilation unit is visible (except where hidden) within the compilation unit and hence can be used as a corresponding program unit. Thus within the compilation unit, the name of a library package can be given in use clauses and can be used to form expanded names; a library subprogram can be called; and instances of a library generic unit can be declared.

The rules given for with clauses are such that the same effect is obtained whether the name of a library unit is mentioned once or more than once by the applicable with clauses, or even within a given with clause.

Example 1 : A main program:

The following is an example of a main program consisting of a single compilation unit: a procedure for printing the real roots of a quadratic equation. The predefined package TEXT_IO and a user-defined package REAL_OPERATIONS (containing the definition of the type REAL and of the packages REAL_IO and REAL_FUNCTIONS) are assumed to be already present in the program library. Such packages may be used by other main programs.

    with TEXT_IO, REAL_OPERATIONS; use REAL_OPERATIONS;
    procedure QUADRATIC_EQUATION is
       A, B, C, D : REAL;
       use REAL_IO,         --  achieves direct visibility of GET and PUT
                                for REAL
           TEXT_IO,         --  achieves direct visibility of PUT for strings
                                and of NEW_LINE
           REAL_FUNCTIONS;  --  achieves direct visibility of SQRT
    begin
       GET(A); GET(B); GET(C);
       D := B**2 - 4.0*A*C;
       if D < 0.0 then
          PUT("Imaginary Roots.");
       else
          PUT("Real Roots : X1 = ");
          PUT((-B - SQRT(D))/(2.0*A)); PUT(" X2 = ");
          PUT((-B + SQRT(D))/(2.0*A));
       end if;
       NEW_LINE; 
    end QUADRATIC_EQUATION;    

Notes on the example:

The with clauses of a compilation unit need only mention the names of those library subprograms and packages whose visibility is actually necessary within the unit. They need not (and should not) mention other library units that are used in turn by some of the units named in the with clauses, unless these other library units are also used directly by the current compilation unit. For example, the body of the package REAL_OPERATIONS may need elementary operations provided by other packages. The latter packages should not be named by the with clause of QUADRATIC_EQUATION since these elementary operations are not directly called within its body.

References: allow, compilation unit, direct visibility, elaboration, generic body, generic unit, hiding, instance, library unit, main program, must, name, package, package body, package declaration, procedure, program unit, secondary unit, simple name, standard predefined package, subprogram body, subprogram declaration, subunit, type, use clause, visibility.

10.1.2. Examples of Compilation Units

[PREVIOUS][UP]

A compilation unit can be split into a number of compilation units. For example, consider the following program.

    procedure PROCESSOR is 

       SMALL : constant := 20;
       TOTAL : INTEGER  := 0; 

       package STOCK is
          LIMIT : constant := 1 
          TABLE : array (1 .. LIMIT) of INTEGER;   
          procedure RESTART;
       end STOCK; 

       package body STOCK is
          procedure RESTART is
          begin
             for N in 1 .. LIMIT loop
                TABLE(N) := N;
             end loop;
          end;
       begin
          RESTART;
       end STOCK; 

       procedure UPDATE(X : INTEGER) is
          use STOCK;
       begin
          ...
          TABLE(X) := TABLE(X) + SMALL;
          ...
       end UPDATE; 

    begin
       ...
       STOCK.RESTART;  -- reinitializes TABLE
       ...
    end PROCESSOR; 

The following three compilation units define a program with an effect equivalent to the above example (the broken lines between compilation units serve to remind the reader that these units need not be contiguous texts).

Example 2 : Several compilation units:

    package STOCK is
       LIMIT : constant := 1 
       TABLE : array (1 .. LIMIT) of INTEGER;
       procedure RESTART;
    end STOCK; 

    ------------------------------------------------- 

    package body STOCK is
       procedure RESTART is
       begin
          for N in 1 .. LIMIT loop
             TABLE(N) := N;
          end loop;
       end;
    begin
       RESTART;
    end STOCK; 

    ------------------------------------------------- 

    with STOCK;
    procedure PROCESSOR is 
       SMALL : constant := 20;
       TOTAL : INTEGER  := 0; 

       procedure UPDATE(X : INTEGER) is
          use STOCK;
       begin
          ...
          TABLE(X) := TABLE(X) + SMALL;
          ...
       end UPDATE;
    begin
       ...
       STOCK.RESTART;  --  reinitializes TABLE
       ...
    end PROCESSOR; 

Note that in the latter version, the package STOCK has no visibility of outer identifiers other than the predefined identifiers (of the package STANDARD). In particular, STOCK does not use any identifier declared in PROCESSOR such as SMALL or TOTAL; otherwise STOCK could not have been extracted from PROCESSOR in the above manner. The procedure PROCESSOR, on the other hand, depends on STOCK and mentions this package in a with clause. This permits the inner occurrences of STOCK in the expanded name STOCK.RESTART and in the use clause.

These three compilation units can be submitted in one or more compilations. For example, it is possible to submit the package specification and the package body together and in this order in a single compilation.

References: compilation unit, declaration, identifier, package, package body, package specification, program, standard package, use clause, visibility, with clause.


[INDEX][CONTENTS]