[Home] [Prev] [Next] [Index]

10.1 Separate Compilation

10.1 Separate Compilation

1
[A program unit is either a package, a task unit, a protected unit, a protected entry, a generic unit, or an explicitly declared subprogram other than an enumeration literal. Certain kinds of program units can be separately compiled. Alternatively, they can appear physically nested within other program units.

2
The text of a program can be submitted to the compiler in one or more compilations. Each compilation is a succession of compilation_units. A compilation_unit contains either the declaration, the body, or a renaming of a program unit.] The representation for a compilation is implementation-defined.

2.a
Implementation defined:  The representation for a compilation.

2.b
Ramification: Some implementations might choose to make a compilation be a source (text) file. Others might allow multiple source files to be automatically concatenated to form a single compilation. Others still may represent the source in a nontextual form such as a parse tree. Note that the RM9X does not even define the concept of a source file.

2.c
Note that a protected subprogram is a subprogram, and therefore a program unit. An instance of a generic unit is a program unit.

2.d
A protected entry is a program unit, but protected entries cannot be separately compiled.

3
A library unit is a separately compiled program unit, and is always a package, subprogram, or generic unit. Library units may have other (logically nested) library units as children, and may have other program units physically nested within them. A root library unit, together with its children and grandchildren and so on, form a subsystem.

Implementation Permissions

4
An implementation may impose implementation-defined restrictions on compilations that contain multiple compilation_units.

4.a
Implementation defined:  Any restrictions on compilations that contain multiple compilation_units.

4.b
Discussion:  For example, an implementation might disallow a compilation that contains two versions of the same compilation unit, or that contains the declarations for library packages P1 and P2, where P1 precedes P2 in the compilation but P1 has a with_clause that mentions P2.

Wording Changes From Ada 83

4.c
The interactions between language issues and environmental issues are left open in Ada 9X.  The environment concept is new. In Ada 83, the concept of the program library, for example, appeared to be quite concrete, although the rules had no force, since implementations could get around them simply by defining various mappings from the concept of an Ada program library to whatever data structures were actually stored in support of separate compilation. Indeed, implementations were encouraged to do so.

4.d
In RM83, it was unclear which was the official definition of "program unit." Definitions appeared in RM83-5, 6, 7, and 9, but not 12. Placing it here seems logical, since a program unit is sort of a potential compilation unit.

10.1.1 Compilation Units - Library Units

1
[A library_item is a compilation unit that is the declaration, body, or renaming of a library unit. Each library unit (except Standard) has a parent unit, which is a library package or generic library package.] A library unit is a child of its parent unit. The root library units are the children of the predefined library package Standard.

1.a
Ramification: Standard is a library unit.

Syntax

2
compilation ::= {compilation_unit}

3
compilation_unit ::=
    context_clause library_item
  | context_clause subunit

4
library_item ::= [private] library_unit_declaration
  | library_unit_body
  | [private] library_unit_renaming_declaration

5
library_unit_declaration ::=
     subprogram_declaration | package_declaration
   | generic_declaration | generic_instantiation

6
library_unit_renaming_declaration ::=
   package_renaming_declaration
| generic_renaming_declaration
| subprogram_renaming_declaration

7
library_unit_body ::= subprogram_body | package_body

8
parent_unit_name ::= name

9
A library unit is a program unit that is declared by a library_item. When a program unit is a library unit, the prefix "library" is used to refer to it (or "generic library" if generic), as well as to its declaration and body, as in "library procedure", "library package_body", or "generic library package". The term compilation unit is used to refer to a compilation_unit. When the meaning is clear from context, the term is also used to refer to the library_item of a compilation_unit or to the proper_body of a subunit [(that is, the compilation_unit without the context_clause and the separate (parent_unit_name))].

9.a
Discussion:  In this example:

9.b
with Ada.Text_IO;
package P is
    ...
end P;

9.c
the term "compilation unit" can refer to this text: "with Ada.Text_IO; package P is ... end P;" or to this text: "package P is ... end P;".  We use this shorthand because it corresponds to common usage.

9.d
We like to use the word "unit" for declaration-plus-body things, and "item" for declaration or body separately (as in declarative_item). The terms "compilation_unit," "compilation unit," and "subunit" are exceptions to this rule. We considered changing "compilation_unit," "compilation unit" to "compilation_item," "compilation item," respectively, but we decided not to.

10
The parent declaration of a library_item (and of the library unit) is the declaration denoted by the parent_unit_name, if any, of the defining_program_unit_name of the library_item. If there is no parent_unit_name, the parent declaration is the declaration of Standard, the library_item is a root library_item, and the library unit (renaming) is a root library unit (renaming). The declaration and body of Standard itself have no parent declaration. The parent unit of a library_item or library unit is the library unit declared by its parent declaration.

10.a
Discussion:  The declaration and body of Standard are presumed to exist from the beginning of time, as it were. There is no way to actually write them, since there is no syntactic way to indicate lack of a parent. An attempt to compile a package Standard would result in Standard.Standard.

10.b
Reason: Library units (other than Standard) have "parent declarations" and "parent units". Subunits have "parent bodies". We didn't bother to define the other possibilities: parent body of a library unit, parent declaration of a subunit, parent unit of a subunit. These are not needed, and might get in the way of a correct definition of "child."

11
[The children of a library unit occur immediately within the declarative region of the declaration of the library unit.] The ancestors of a library unit are itself, its parent, its parent's parent, and so on. [(Standard is an ancestor of every library unit.)] The descendant relation is the inverse of the ancestor relation.

11.a
Reason: These definitions are worded carefully to avoid defining subunits as children.  Only library units can be children.

11.b
We use the unadorned term "ancestors" here to concisely define both "ancestor unit" and "ancestor declaration."

12
A library_unit_declaration or a library_unit_renaming_declaration is private if the declaration is immediately preceded by the reserved word private; it is otherwise public.  A library unit is private or public according to its declaration. The public descendants of a library unit are the library unit itself, and the public descendants of its public children. Its other descendants are private descendants.

12.a
Discussion:  The first concept defined here is that a library_item is either public or private (not in relation to anything else - it's just a property of the library unit). The second concept is that a library_item is a public descendant or private descendant of a given ancestor. A given library_item can be a public descendant of one of its ancestors, but a private descendant of some other ancestor.

12.b
A subprogram declared by a subprogram_body (as opposed to a subprogram_declaration) is always public, since the syntax rules disallow the reserved word private on a body.

12.c
Note that a private library unit is a public descendant of itself, but a private descendant of its parent. This is because it is visible outside itself - its privateness means that it is not visible outside its parent.

12.d
Private children of Standard are legal, and follow the normal rules. It is intended that implementations might have some method for taking an existing environment, and treating it as a package to be "imported" into another environment, treating children of Standard in the imported environment as children of the imported package.

12.e
Ramification: Suppose we have a public library unit A, a private library unit A.B, and a public library unit A.B.C. A.B.C is a public descendant of itself and of A.B, but a private descendant of A; since A.B is private to A, we don't allow A.B.C to escape outside A either. This is similar to the situation that would occur with physical nesting, like this:

12.f
package A is
private
    package B is
        package C is
        end C;
    private
    end B;
end A;

12.g
Here, A.B.C is visible outside itself and outside A.B, but not outside A. (Note that this example is intended to illustrate the visibility of program units from the outside; the visibility within child units is not quite identical to that of physically nested units, since child units are nested after their parent's declaration.)

Legality Rules

13
The parent unit of a library_item shall be a [library] package or generic [library] package.

14
If a defining_program_unit_name of a given declaration or body has a parent_unit_name, then the given declaration or body shall be a library_item. The body of a program unit shall be a library_item if and only if the declaration of the program unit is a library_item. In a library_unit_renaming_declaration, the [(old)] name shall denote a library_item.

14.a
Discussion:  We could have allowed nested program units to be children of other program units; their semantics would make sense. We disallow them to keep things simpler and because they wouldn't be particularly useful.

15
A parent_unit_name [(which can be used within a defining_program_unit_name of a library_item and in the separate clause of a subunit)], and each of its prefixes, shall not denote a renaming_declaration. [On the other hand, a name that denotes a library_unit_renaming_declaration is allowed in a with_clause and other places where the name of a library unit is allowed.]

16
If a library package is an instance of a generic package, then every child of the library package shall either be itself an instance or be a renaming of a library unit.

16.a
Discussion:  A child of an instance of a given generic unit will often be an instance of a (generic) child of the given generic unit. This is not required, however.

16.b
Reason: Instances are forbidden from having noninstance children for two reasons:

16.c 1. We want all source code that can depend on information from the private part of a library unit to be inside the "subsystem" rooted at the library unit. If an instance of a generic unit were allowed to have a noninstance as a child, the source code of that child might depend on information from the private part of the generic unit, even though it is outside the subsystem rooted at the generic unit.

16.d 2. Disallowing noninstance children simplifies the description of the semantics of children of generic packages.

17
A child of a generic library package shall either be itself a generic unit or be a renaming of some other child of the same generic unit. The renaming of a child of a generic package shall occur only within the declarative region of the generic package.

18
A child of a parent generic package shall be instantiated or renamed only within the declarative region of the parent generic.

19
For each declaration or renaming of a generic unit as a child of some parent generic package, there is a corresponding declaration nested immediately within each instance of the parent. [This declaration is visible only within the scope of a with_clause that mentions the child generic unit.]

19.a
Implementation Note: Within the child, like anything nested in a generic unit, one can make up-level references to the current instance of its parent, and thereby gain access to the formal parameters of the parent, to the types declared in the parent, etc. This "nesting" model applies even within the generic_formal_part of the child, as it does for a generic child of a nongeneric unit.

19.b
Ramification: Suppose P is a generic library package, and P.C is a generic child of P. P.C can be instantiated inside the declarative region of P. Outside P, P.C can be mentioned only in a with_clause. Conceptually, an instance I of P is a package that has a nested generic unit called I.C. Mentioning P.C in a with_clause allows I.C to be instantiated. I need not be a library unit, and the instantiation of I.C need not be a library unit. If I is a library unit, and an instance of I.C is a child of I, then this instance has to be called something other than C.

20
A library subprogram shall not override a primitive subprogram.

20.a
Reason: This prevents certain obscure anomalies. For example, if a library subprogram were to override a subprogram declared in its parent package, then in a compilation unit that depends indirectly on the library subprogram, the library subprogram could hide the overridden operation from all visibility, but the library subprogram itself would not be visible.

20.b
Note that even without this rule, such subprograms would be illegal for tagged types, because of the freezing rules.

21
The defining name of a function that is a compilation unit shall not be an operator_symbol.

21.a
Reason: Since overloading is not permitted among compilation units, it seems unlikely that it would be useful to define one as an operator.  Note that a subunit could be renamed within its parent to be an operator.

Static Semantics

22
A subprogram_renaming_declaration that is a library_unit_renaming_declaration is a renaming-as-declaration, not a renaming-as-body.

23
[There are two kinds of dependences among compilation units:

24 ·
The semantic dependences (see below) are the ones needed to check the compile-time rules across compilation unit boundaries; a compilation unit depends semantically on the other compilation units needed to determine its legality. The visibility rules are based on the semantic dependences.

25 ·
The elaboration dependences (see 10.2) determine the order of elaboration of library_items.

]

25.a
Discussion:  Don't confuse these kinds of dependences with the run-time dependences among tasks and masters defined in 9.3, "Task Dependence - Termination of Tasks".

26
A library_item depends semantically upon its parent declaration. A subunit depends semantically upon its parent body. A library_unit_body depends semantically upon the corresponding library_unit_declaration, if any.

26.a
Discussion:  The "if any" is necessary because library subprograms are not required to have a subprogram_declaration.

A compilation unit depends semantically upon each library_item mentioned in a with_clause of the compilation unit. In addition, if a given compilation unit contains an attribute_reference of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. The semantic dependence relationship is transitive.

26.b
To be honest: If a given compilation unit contains a choice_parameter_specification, then the given compilation unit depends semantically upon the declaration of Ada.Exceptions.

26.c
If a given compilation unit contains a pragma with an argument of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit.

26.d
Discussion:  For example, a compilation unit containing X'Address depends semantically upon the declaration of package System.

26.e
For the Address attribute, this fixes a hole in Ada 83. Note that in almost all cases, the dependence will need to exist due to with_clauses, even without this rule. Hence, the rule has very little effect on programmers.

26.f
Note that the semantic dependence does not have the same effect as a with_clause; in order to denote a declaration in one of those packages, a with_clause will generally be needed.

26.g
Note that no special rule is needed for an attribute_definition_clause, since an expression after use will require semantic dependence upon the compilation unit containing the type_declaration of interest.

NOTES

27 1
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.

27.a
Ramification: Such pragmas cannot have any arguments that are names, by a previous rule of this subclause. A compilation can even be entirely empty, which is probably not useful.

27.b
Some interesting properties of the three kinds of dependence: The elaboration dependences also include the semantic dependences, except that subunits are taken together with their parents. The semantic dependences partly determine the order in which the compilation units appear in the environment at compile time. At run time, the order is partly determined by the elaboration dependences.

27.c
The model whereby a child is inside its parent's declarative region, after the parent's declaration, as explained in 8.1, has the following ramifications:

27.d ·   
The restrictions on "early" use of a private type (RM83-7.4.1(4)) or a deferred constant (RM83-7.4.3(2)) do not apply to uses in child units, because they follow the full declaration.
27.e ·   
A library subprogram is never primitive, even if its profile includes a type declared immediately within the parent's package_specification, because the child is not declared immediately within the same package_specification as the type (so it doesn't declare a new primitive subprogram), and because the child is forbidden from overriding an old primitive subprogram. It is immediately within the same declarative region, but not the same package_specification. Thus, for a tagged type, it is not possible to call a child subprogram in a dispatching manner. (This is also forbidden by the freezing rules.) Similarly, it is not possible for the user to declare primitive subprograms of the types declared in the declaration of Standard, such as Integer (even if the rules were changed to allow a library unit whose name is an operator symbol).
27.f ·   
When the parent unit is "used" the simple names of the with'd child units are directly visible (see 8.4, "Use Clauses").
27.g ·   
When a parent body with's its own child, the defining name of the child is directly visible, and the parent body is not allowed to include a declaration of a homograph of the child unit immediately within the declarative_part of the body (RM83-8.3(17)).
27.h
Note that "declaration of a library unit" is different from "library_unit_declaration" - the former includes subprogram_body. Also, we sometimes really mean "declaration of a view of a library unit", which includes library_unit_renaming_declarations.

27.i
The visibility rules generally imply that the renamed view of a library_unit_renaming_declaration has to be mentioned in a with_clause of the library_unit_renaming_declaration.

27.j
To be honest: The real rule is that the renamed library unit has to be visible in the library_unit_renaming_declaration.

27.k
Reason: In most cases, "has to be visible" means there has to be a with_clause. However, it is possible in obscure cases to avoid the need for a with_clause; in particular, a compilation unit such as "package P.Q renames P;" is legal with no with_clauses (though not particularly interesting). ASCII is physically nested in Standard, and so is not a library unit, and cannot be renamed as a library unit.

28 2
The designator of a library function cannot be an operator_symbol, but a nonlibrary renaming_declaration is allowed to rename a library function as an operator. Within a partition, two library subprograms are required to have distinct 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 to denote a root library unit L (unless the declaration of Standard is hidden) since root library unit declarations occur immediately within the declarative region of package Standard.

Examples

29
Examples of library units:

30
package Rational_Numbers.IO is  -- public child of Rational_Numbers, see 7.1
   procedure Put(R : in  Rational);
   procedure Get(R : out Rational);
end Rational_Numbers.IO;

31
private procedure Rational_Numbers.Reduce(R : in out Rational);
                                -- private child of Rational_Numbers

32
with Rational_Numbers.Reduce;   -- refer to a private child
package body Rational_Numbers is
   ...
end Rational_Numbers;

33
with Rational_Numbers.IO; use Rational_Numbers;
with Ada.Text_io;               -- see A.10
procedure Main is               -- a root library procedure
   R : Rational;
begin
   R := 5/3;                    -- construct a rational number, see 7.1
   Ada.Text_IO.Put("The answer is: ");
   IO.Put(R);
   Ada.Text_IO.New_Line;
end Main;

34
with Rational_Numbers.IO;
package Rational_IO renames Rational_Numbers.IO;
                                -- a library unit renaming declaration

35
Each of the above library_items can be submitted to the compiler separately.

35.a
Discussion:  Example of a generic package with children:

35.b
generic
   type Element is private;
   with function Image(E : Element) return String;
package Generic_Bags is
   type Bag is limited private; --A bag of Elements.
   procedure Add(B : in out Bag; E : Element);
   function Bag_Image(B : Bag) return String;
private
   type Bag is ...;
end Generic_Bags;

35.c
generic
package
Generic_Bags.Generic_Iterators is
   ... --various additional operations on Bags.

35.d
   generic
      with procedure Use_Element(E : in Element);
         --Called once per bag element.
   procedure Iterate(B : in Bag);
end Generic_Bags.Generic_Iterators;

35.e
A package that instantiates the above generic units:

35.f
with Generic_Bags;
with Generic_Bags.Generic_Iterators;
package My_Abstraction is
    type My_Type is ...;
    function Image(X : My_Type) return String;
    package Bags_Of_My_Type is new Generic_Bags(My_Type, Image);
    package Iterators_Of_Bags_Of_My_Type is new Bags_Of_My_Type.Generic_Iterators;
end My_Abstraction;

35.g
In the above example, Bags_Of_My_Type has a nested generic unit called Generic_Iterators. The second with_clause makes that nested unit visible.

35.h
Here we show how the generic body could depend on one of its own children:

35.i
with Generic_Bags.Generic_Iterators;
package body Generic_Bags is
   procedure Add(B : in out Bag; E : Element) is ... end Add;

35.j
   package Iters is new Generic_Iterators;

35.k
   function Bag_Image(B : Bag) return String is
      Buffer : String(1..10_000);
      Last : Integer := 0;

35.l
      procedure Append_Image(E : in Element) is
         Im : constant String := Image(E);
      begin
         if Last /= 0 then --Insert a comma.
            Last := Last + 1;
            Buffer(Last) := ',';
         end if;
         Buffer(Last+1 .. Last+Im'Length) := Im;
         Last := Last + Im'Length;
      end Append_Image;

35.m
      procedure Append_All is new Iters.Iterate(Append_Image);
   begin
      Append_All(B);
      return Buffer(1..Last);
   end Bag_Image;
end Generic_Bags;

Extensions to Ada 83

35.n
The syntax rule for library_item is modified to allow the reserved word private before a library_unit_declaration.

35.o
Children (other than children of Standard) are new in Ada 9X.

35.p
Library unit renaming is new in Ada 9X.

Wording Changes From Ada 83

35.q
Standard is considered a library unit in Ada 9X. This simplifies the descriptions, since it implies that the parent of each library unit is a library unit. (Standard itself has no parent, of course.) As in Ada 83, the language does not define any way to recompile Standard, since the name given in the declaration of a library unit is always interpreted in relation to Standard. That is, an attempt to compile a package Standard would result in Standard.Standard.

10.1.2 Context Clauses - With Clauses

1
[A context_clause is used to specify the library_items whose names are needed within a compilation unit.]

Language Design Principles

1.a
The reader should be able to understand a context_clause without looking ahead. Similarly, when compiling a context_clause, the compiler should not have to look ahead at subsequent context_items, nor at the compilation unit to which the context_clause is attached. (We have not completely achieved this.)

Syntax

2
context_clause ::= {context_item}

3
context_item ::= with_clause | use_clause

4
with_clause ::= with library_unit_name {, library_unit_name};

Name Resolution Rules

5
The scope of a with_clause that appears on a library_unit_declaration or library_unit_renaming_declaration consists of the entire declarative region of the declaration[, which includes all children and subunits]. The scope of a with_clause that appears on a body consists of the body[, which includes all subunits].

5.a
Discussion:  Suppose a with_clause of a public library unit mentions one of its private siblings. (This is only allowed on the body of the public library unit.) We considered making the scope of that with_clause not include the visible part of the public library unit. (This would only matter for a subprogram_body, since those are the only kinds of body that have a visible part, and only if the subprogram_body completes a subprogram_declaration, since otherwise the with_clause would be illegal.) We did not put in such a rule for two reasons: (1) It would complicate the wording of the rules, because we would have to split each with_clause into pieces, in order to correctly handle "with P, Q;" where P is public and Q is private. (2) The conformance rules prevent any problems. It doesn't matter if a type name in the spec of the body denotes the completion of a private_type_declaration.

5.b
A with_clause also affects visibility within subsequent use_clauses and pragmas of the same context_clause, even though those are not in the scope of the with_clause.

6
A library_item is mentioned in a with_clause if it is denoted by a library_unit_name or a prefix in the with_clause.

6.a
Discussion:  With_clauses control the visibility of declarations or renamings of library units. Mentioning a root library unit in a with_clause makes its declaration directly visible. Mentioning a non-root library unit makes its declaration visible. See Section 8 for details.

6.b
Note that this rule implies that "with A.B.C;" is equivalent to "with A, A.B, A.B.C;" The reason for making a with_clause apply to all the ancestor units is to avoid "visibility holes" - situations in which an inner program unit is visible while an outer one is not. Visibility holes would cause semantic complexity and implementation difficulty.

7
[Outside its own declarative region, the declaration or renaming of a library unit can be visible only within the scope of a with_clause that mentions it. The visibility of the declaration or renaming of a library unit otherwise follows from its placement in the environment.]

Legality Rules

8
If a with_clause of a given compilation_unit mentions a private child of some library unit, then the given compilation_unit shall be either the declaration of a private descendant of that library unit or the body or subunit of a [(public or private)] descendant of that library unit.

8.a
Reason: The purpose of this rule is to prevent a private child from being visible (or even semantically depended-on) from outside the subsystem rooted at its parent.

8.b
Discussion:  This rule violates the one-pass context_clauses Language Design Principle.  We rationalize this by saying that at least that Language Design Principle works for legal compilation units.

8.c
Example:

8.d
package A is
end
A;

8.e
package A.B is
end
A.B;

8.f
private package A.B.C is
end
A.B.C;

8.g
package A.B.C.D is
end
A.B.C.D;

8.h
with A.B.C; -- (1)
private package A.B.X is
end
A.B.X;

8.i
package A.B.Y is
end
A.B.Y;

8.j
with A.B.C; -- (2)
package body A.B.Y is
end
A.B.Y;

8.k
(1) is OK because it's a private child of A.B - it would be illegal if we made A.B.X a public child of A.B. (2) is OK because it's the body of a child of A.B. It would be illegal to say "with A.B.C;" on any library_item whose name does not start with "A.B". Note that mentioning A.B.C.D in a with_clause automatically mentions A.B.C as well, so "with A.B.C.D;" is illegal in the same places as "with A.B.C;".

8.l
To be honest: For the purposes of this rule, if a subprogram_body has no preceding subprogram_declaration, the subprogram_body should be considered a declaration and not a body. Thus, it is illegal for such a subprogram_body to mention one of its siblings in a with_clause if the sibling is a private library unit.

NOTES

9 3
A library_item mentioned in a with_clause of a compilation unit is visible within the compilation unit and hence acts just like an ordinary declaration. Thus, within a compilation unit that mentions its declaration, 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 generic library unit can be declared. If a child of a parent generic package is mentioned in a with_clause, then the corresponding declaration nested within each visible instance is visible within the compilation unit.

9.a
Ramification: 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.

9.b
If a with_clause mentions a library_unit_renaming_declaration, it only "mentions" the prefixes appearing explicitly in the with_clause (and the renamed view itself); the with_clause is not defined to mention the ancestors of the renamed entity. Thus, if X renames Y.Z, then "with X;" does not make the declarations of Y or Z visible. Note that this does not cause the dreaded visibility holes mentioned above.

Extensions to Ada 83

9.c
The syntax rule for with_clause is modified to allow expanded name notation.

9.d
A use_clause in a context_clause may be for a package (or type) nested in a library package.

Wording Changes From Ada 83

9.e
The syntax rule for context_clause is modified to more closely reflect the semantics. The Ada 83 syntax rule implies that the use_clauses that appear immediately after a particular with_clause are somehow attached to that with_clause, which is not true. The new syntax allows a use_clause to appear first, but that is prevented by a textual rule that already exists in Ada 83.

9.f
The concept of "scope of a with_clause" (which is a region of text) replaces RM83's notion of "apply to" (a with_clause applies to a library_item) The visibility rules are interested in a region of text, not in a set of compilation units.

9.g
No need to define "apply to" for use_clauses. Their semantics are fully covered by the "scope (of a use_clause)" definition in 8.4.

10.1.3 Subunits of Compilation Units

1
[Subunits are like child units, with these (important) differences: subunits support the separate compilation of bodies only (not declarations); the parent contains a body_stub to indicate the existence and place of each of its subunits; declarations appearing in the parent's body can be visible within the subunits.]

Syntax

2
body_stub ::= subprogram_body_stub | package_body_stub | task_body_stub | protected_body_stub

3
subprogram_body_stub ::= subprogram_specification is separate;

3.a
Discussion:  Although this syntax allows a parent_unit_name, that is disallowed by 10.1.1, "Compilation Units - Library Units".

4
package_body_stub ::= package body defining_identifier is separate;

5
task_body_stub ::= task body defining_identifier is separate;

6
protected_body_stub ::= protected body defining_identifier is separate;

7
subunit ::= separate (parent_unit_name) proper_body

Legality Rules

8
The parent body of a subunit is the body of the program unit denoted by its parent_unit_name. The term subunit is used to refer to a subunit and also to the proper_body of a subunit.

9
The parent body of a subunit shall be present in the current environment, and shall contain a corresponding body_stub with the same defining_identifier as the subunit.

9.a
Discussion:  This can't be a Name Resolution Rule, because a subunit is not a complete context.

10
A package_body_stub shall be the completion of a package_declaration or generic_package_declaration; a task_body_stub shall be the completion of a task_declaration; a protected_body_stub shall be the completion of a protected_declaration.

11
In contrast, a subprogram_body_stub need not be the completion of a previous declaration, [in which case the _stub declares the subprogram]. If the _stub is a completion, it shall be the completion of a subprogram_declaration or generic_subprogram_declaration. The profile of a subprogram_body_stub that completes a declaration shall conform fully to that of the declaration.

11.a
Discussion:  The part about subprogram_body_stubs echoes the corresponding rule for subprogram_bodies in 6.3, "Subprogram Bodies".

12
A subunit that corresponds to a body_stub shall be of the same kind (package_, subprogram_, task_, or protected_) as the body_stub. The profile of a subprogram_body subunit shall be fully conformant to that of the corresponding body_stub.

13
A body_stub shall appear immediately within the declarative_part of a compilation unit body. This rule does not apply within an instance of a generic unit.

13.a
Discussion:  This is a methodological restriction; that is, it is not necessary for the semantics of the language to make sense.

14
The defining_identifiers of all body_stubs that appear immediately within a particular declarative_part shall be distinct.

Post-Compilation Rules

15
For each body_stub, there shall be a subunit containing the corresponding proper_body.

NOTES

16 4
The rules in 10.1.4, "The Compilation Process" say that a body_stub is equivalent to the corresponding proper_body.  This implies:

17 ·
Visibility within a subunit is the visibility that would be obtained at the place of the corresponding body_stub (within the parent body) if the context_clause of the subunit were appended to that of the parent body.

17.a
Ramification: Recursively. Note that this transformation might make the parent illegal; hence it is not a true equivalence, but applies only to visibility within the subunit.

18 ·
The effect of the elaboration of a body_stub is to elaborate the subunit.

18.a
Ramification: The elaboration of a subunit is part of its parent body's elaboration, whereas the elaboration of a child unit is not part of its parent declaration's elaboration.

18.b
Ramification: A library_item that is mentioned in a with_clause of a subunit can be hidden (from direct visiblity) by a declaration (with the same identifier) given in the subunit. Moreover, such a library_item can even be hidden by a declaration given within the parent body since a library unit is declared in its parent's declarative region; this however does not affect the interpretation of the with_clauses themselves, since only library_items are visible or directly visible in with_clauses.

18.c
The body of a protected operation cannot be a subunit. This follows from the syntax rules. The body of a protected unit can be a subunit.

Examples

19
The package Parent is first written without subunits:

20
package Parent is
    procedure Inner;
end Parent;

21
with Ada.Text_IO;
package body Parent is
    Variable : String := "Hello, there.";
    procedure Inner is
    begin
        Ada.Text_IO.Put_Line(Variable);
    end Inner;
end Parent;

22
The body of procedure Inner may be turned into a subunit by rewriting the package body as follows (with the declaration of Parent remaining the same):

23
package body Parent is
    Variable : String := "Hello, there.";
    procedure Inner is separate;
end Parent;

24
with Ada.Text_IO;
separate(Parent)
procedure Inner is
begin
    Ada.Text_IO.Put_Line(Variable);
end Inner;

Extensions to Ada 83

24.a
Subunits of the same ancestor library unit are no longer restricted to have distinct identifiers. Instead, we require only that the full expanded names be distinct.

10.1.4 The Compilation Process

1
Each compilation unit submitted to the compiler is compiled in the context of an environment declarative_part (or simply, an environment), which is a conceptual declarative_part that forms the outermost declarative region of the context of any compilation. At run time, an environment forms the declarative_part of the body of the environment task of a partition (see 10.2, "Program Execution").

1.a
Ramification: At compile time, there is no particular construct that the declarative region is considered to be nested within - the environment is the universe.

1.b
To be honest: The environment is really just a portion of a declarative_part, since there might, for example, be bodies that do not yet exist.

2
The declarative_items of the environment are library_items appearing in an order such that there are no forward semantic dependences. Each included subunit occurs in place of the corresponding stub. The visibility rules apply as if the environment were the outermost declarative region, except that with_clauses are needed to make declarations of library units visible (see 10.1.2).

3
The mechanisms for creating an environment and for adding and replacing compilation units within an environment are implementation defined.

3.a
Implementation defined:  The mechanisms for creating an environment and for adding and replacing compilation units.

3.b
Ramification: The traditional model, used by most Ada 83 implementations, is that one places a compilation unit in the environment by compiling it. Other models are possible. For example, an implementation might define the environment to be a directory; that is, the compilation units in the environment are all the compilation units in the source files contained in the directory. In this model, the mechanism for replacing a compilation unit with a new one is simply to edit the source file containing that compilation unit.

Name Resolution Rules

4
If a library_unit_body that is a subprogram_body is submitted to the compiler, it is interpreted only as a completion if a library_unit_declaration for a subprogram or a generic subprogram with the same defining_program_unit_name already exists in the environment (even if the profile of the body is not type conformant with that of the declaration); otherwise the subprogram_body is interpreted as both the declaration and body of a library subprogram.

4.a
Ramification: The principle here is that a subprogram_body should be interpreted as only a completion if and only if it "might" be legal as the completion of some preexisting declaration, where "might" is defined in a way that does not require overload resolution to determine.

4.b
Hence, if the preexisting declaration is a subprogram_declaration or generic_subprogram_declaration, we treat the new subprogram_body as its completion, because it "might" be legal. If it turns out that the profiles don't fully conform, it's an error. In all other cases (the preexisting declaration is a package or a generic package, or an instance of a generic subprogram, or a renaming, or a "spec-less" subprogram, or in the case where there is no preexisting thing), the subprogram_body declares a new subprogram.

4.c
See also AI-00266/09.

Legality Rules

5
When a compilation unit is compiled, all compilation units upon which it depends semantically shall already exist in the environment; the set of these compilation units shall be consistent in the sense that the new compilation unit shall not semantically depend (directly or indirectly) on two different versions of the same compilation unit, nor on an earlier version of itself.

5.a
Discussion:  For example, if package declarations A and B both say "with X;", and the user compiles a compilation unit that says "with A, B;", then the A and B have to be talking about the same version of X.

5.b
Ramification: What it means to be a "different version" is not specified by the language.  In some implementations, it means that the compilation unit has been recompiled.  In others, it means that the source of the compilation unit has been edited in some significant way.

5.c
Note that an implementation cannot require the existence of compilation units upon which the given one does not semantically depend. For example, an implementation is required to be able to compile a compilation unit that says "with A;" when A's body does not exist. It has to be able to detect errors without looking at A's body.

5.d
Similarly, the implementation has to be able to compile a call to a subprogram for which a pragma Inline has been specified without seeing the body of that subprogram - inlining would not be achieved in this case, but the call is still legal.

Implementation Permissions

6
The implementation may require that a compilation unit be legal before inserting it into the environment.

7
When a compilation unit that declares or renames a library unit is added to the environment, the implementation may remove from the environment any preexisting library_item with the same defining_program_unit_name. When a compilation unit that is a subunit or the body of a library unit is added to the environment, the implementation may remove from the environment any preexisting version of the same compilation unit. When a given compilation unit is removed from the environment, the implementation may also remove any compilation unit that depends semantically upon the given one. If the given compilation unit contains the body of a subprogram to which a pragma Inline applies, the implementation may also remove any compilation unit containing a call to that subprogram.

7.a
Ramification: The permissions given in this paragraph correspond to the traditional model, where compilation units enter the environment by being compiled into it, and the compiler checks their legality at that time. A implementation model in which the environment consists of all source files in a given directory might not want to take advantage of these permissions. Compilation units would not be checked for legality as soon as they enter the environment; legality checking would happen later, when compilation units are compiled. In this model, compilation units might never be automatically removed from the environment; they would be removed when the user explicitly deletes a source file.

7.b
Note that the rule is recursive: if the above permission is used to remove a compilation unit containing an inlined subprogram call, then compilation units that depend semantically upon the removed one may also be removed, and so on.

7.c
Note that here we are talking about dependences among existing compilation units in the environment; it doesn't matter what with_clauses are attached to the new compilation unit that triggered all this.

7.d
An implementation may have other modes in which compilation units in addition to the ones mentioned above are removed. For example, an implementation might inline subprogram calls without an explicit pragma Inline. If so, it either has to have a mode in which that optimization is turned off, or it has to automatically regenerate code for the inlined calls without requiring the user to resubmit them to the compiler.

NOTES

8 5
The rules of the language are enforced across compilation and compilation unit boundaries, just as they are enforced within a single compilation unit.

8.a
Ramification: Note that Section 1 requires an implementation to detect illegal compilation units at compile time.

9 6
An implementation may support a concept of a library, which contains library_items. If multiple libraries are supported, the implementation has to define how a single environment is constructed when a compilation unit is submitted to the compiler. Naming conflicts between different libraries might be resolved by treating each library as the root of a hierarchy of child library units.

9.a
Implementation Note: Alternatively, naming conflicts could be resolved via some sort of hiding rule.

9.b
Discussion:  For example, the implementation might support a command to import library Y into library X. If a root library unit called LU (that is, Standard.LU) exists in Y, then from the point of view of library X, it could be called Y.LU. X might contain library units that say, "with Y.LU;".

10 7
A compilation unit containing an instantiation of a separately compiled generic unit does not semantically depend on the body of the generic unit. Therefore, replacing the generic body in the environment does not result in the removal of the compilation unit containing the instantiation.

10.a
Implementation Note: Therefore, implementations have to be prepared to automatically instantiate generic bodies at link-time, as needed.  This might imply a complete automatic recompilation, but it is the intent of the language that generic bodies can be (re)instantiated without forcing all of the compilation units that semantically depend on the compilation unit containing the instantiation to be recompiled.

10.1.5 Pragmas and Program Units

1
[This subclause discusses pragmas related to program units, library units, and compilations.]

Name Resolution Rules

2
Certain pragmas are defined to be program unit pragmas. A name given as the argument of a program unit pragma shall resolve to denote the declarations or renamings of one or more program units that occur immediately within the declarative region or compilation in which the pragma immediately occurs, or it shall resolve to denote the declaration of the immediately enclosing program unit (if any); the pragma applies to the denoted program unit(s). If there are no names given as arguments, the pragma applies to the immediately enclosing program unit.

2.a
Ramification: The fact that this is a Name Resolution Rule means that the pragma will not apply to declarations from outer declarative regions.

Legality Rules

3
A program unit pragma shall appear in one of these places:

4 ·
At the place of a compilation_unit, in which case the pragma shall immediately follow in the same compilation (except for other pragmas) a library_unit_declaration that is a subprogram_declaration, generic_subprogram_declaration, or generic_instantiation, and the pragma shall have an argument that is a name denoting that declaration.

4.a
Ramification: The name has to denote the immediately preceding library_unit_declaration.

5 ·
Immediately within the declaration of a program unit and before any nested declaration, in which case the argument, if any, shall be a direct_name that denotes the immediately enclosing program unit declaration.

5.a
Ramification: The argument is optional in this case.

6 ·
At the place of a declaration other than the first, of a declarative_part or program unit declaration, in which case the pragma shall have an argument, which shall be a direct_name that denotes one or more of the following (and nothing else): a subprogram_declaration, a generic_subprogram_declaration, or a generic_instantiation, of the same declarative_part or program unit declaration.

6.a
Ramification: If you want to denote a subprogram_body that is not a completion, or a package_declaration, for example, you have to put the pragma inside.

7
Certain program unit pragmas are defined to be library unit pragmas. The name, if any, in a library unit pragma shall denote the declaration of a library unit.

7.a
Ramification: This, together with the rules for program unit pragmas above, implies that if a library unit pragma applies to a subprogram_declaration (and similar things), it has to appear immediately after the compilation_unit, whereas if the pragma applies to a package_declaration, a subprogram_body that is not a completion (and similar things), it has to appear inside, as the first declarative_item.

Post-Compilation Rules

8
Certain pragmas are defined to be configuration pragmas; they shall appear before the first compilation_unit of a compilation. [They are generally used to select a partition-wide or system-wide option.] The pragma applies to all compilation_units appearing in the compilation, unless there are none, in which case it applies to all future compilation_units compiled into the same environment.

Implementation Permissions

9
An implementation may place restrictions on configuration pragmas, so long as it allows them when the environment contains no library_items other than those of the predefined environment.

10.1.6 Environment-Level Visibility Rules

1
[The normal visibility rules do not apply within a parent_unit_name or a context_clause, nor within a pragma that appears at the place of a compilation unit. The special visibility rules for those contexts are given here.]

Static Semantics

2
Within the parent_unit_name at the beginning of a library_item, and within a with_clause, the only declarations that are visible are those that are library_items of the environment, and the only declarations that are directly visible are those that are root library_items of the environment. Notwithstanding the rules of 4.1.3, an expanded name in a with_clause may consist of a prefix that denotes a generic package and a selector_name that denotes a child of that generic package. [(The child is necessarily a generic unit; see 10.1.1.)]

2.a
Ramification: In "package P.Q.R is ... end P.Q.R;", this rule requires P to be a root library unit, and Q to be a library unit (because those are the things that are directly visible and visible). Note that visibility does not apply between the "end" and the ";".

2.b
Physically nested declarations are not visible at these places.

2.c
Reason: Although Standard is visible at these places, it is impossible to name it, since it is not directly visible, and it has no parent.

2.d
Reason: The "notwithstanding" part allows "with A.B;" where A is a generic library package and B is one of its (generic) children. This is necessary because it is not normally legal to use an expanded name to reach inside a generic package.

3
Within a use_clause or pragma that is within a context_clause, each library_item mentioned in a previous with_clause of the same context_clause is visible, and each root library_item so mentioned is directly visible. In addition, within such a use_clause, if a given declaration is visible or directly visible, each declaration that occurs immediately within the given declaration's visible part is also visible. No other declarations are visible or directly visible.

3.a
Discussion:  Note the word "same". For example, if a with_clause on a declaration mentions X, this does not make X visible in use_clauses and pragmas that are on the body. The reason for this rule is the one-pass context_clauses Language Design Principle.

3.b
Note that the second part of the rule does not mention pragmas.

4
Within the parent_unit_name of a subunit, library_items are visible as they are in the parent_unit_name of a library_item; in addition, the declaration corresponding to each body_stub in the environment is also visible.

4.a
Ramification: For a subprogram without a separate subprogram_declaration, the body_stub itself is the declaration.

5
Within a pragma that appears at the place of a compilation unit, the immediately preceding library_item and each of its ancestors is visible. The ancestor root library_item is directly visible.

Wording Changes From Ada 83

5.a
The special visibility rules that apply within a parent_unit_name or a context_clause, and within a pragma that appears at the place of a compilation_unit are clarified.

5.b
Note that a context_clause is not part of any declarative region.

5.c
We considered making the visibility rules within parent_unit_names and context_clauses follow from the context of compilation. However, this attempt failed for various reasons. For example, it would require use_clauses in context_clauses to be within the declarative region of Standard, which sounds suspiciously like a kludge. And we would still need a special rule to prevent seeing things (in our own context_clause) that were with-ed by our parent, etc.



[Home] [Prev] [Next] [Index]

documentation@rational.com
Copyright © 1993-1998, Rational Software Corporation.   All rights reserved.