Annotated Ada Reference ManualLegal Information
Table of Contents   Index   References   Search   Previous   Next 

 12.6 Formal Subprograms

1
[{generic formal subprogram} {formal subprogram, generic} Formal subprograms can be used to pass callable entities to a generic unit.] 

Language Design Principles

1.a
Generic formal subprograms are like renames of the explicit_generic_actual_parameter.

Syntax

2/2
{AI95-00260-02} formal_subprogram_declaration ::= formal_concrete_subprogram_declaration
    | formal_abstract_subprogram_declaration
 with subprogram_specification [is subprogram_default];
2.1/2
{AI95-00260-02} formal_concrete_subprogram_declaration ::= 
     with subprogram_specification [is subprogram_default];
2.2/2
{AI95-00260-02} formal_abstract_subprogram_declaration ::= 
     with subprogram_specification is abstract [subprogram_default];
3/2
{AI95-00348-01} subprogram_default ::= default_name | <> | null
4
default_name ::= name
4.1/2
{AI95-00260-02} {AI95-00348-01} A subprogram_default of null shall not be specified for a formal function or for a formal_abstract_subprogram_declaration.
4.a/2
Reason: There are no null functions because the return value has to be constructed somehow. We don't allow null for abstract formal procedures, as the operation is dispatching. It doesn't seem appropriate (or useful) to say that the implementation of something is null in the formal type and all possible descendants of that type. This also would define a dispatching operation that doesn't correspond to a slot in the tag of the controlling type, which would be a new concept. Finally, additional rules would be needed to define the meaning of a dispatching null procedure (for instance, the convention of such a subprogram should be intrinsic, but that's not what the language says). It doesn't seem worth the effort. 

Name Resolution Rules

5
{expected profile (formal subprogram default_name) [partial]} The expected profile for the default_name, if any, is that of the formal subprogram. 
5.a
Ramification: This rule, unlike others in this clause, is observed at compile time of the generic_declaration.
5.b
The evaluation of the default_name takes place during the elaboration of each instantiation that uses the default, as defined in 12.3, “Generic Instantiation”. 
6
{expected profile (formal subprogram actual) [partial]} For a generic formal subprogram, the expected profile for the actual is that of the formal subprogram. 

Legality Rules

7
The profiles of the formal and any named default shall be mode-conformant. {mode conformance (required)}
7.a
Ramification: This rule, unlike others in this clause, is checked at compile time of the generic_declaration.
8
The profiles of the formal and actual shall be mode-conformant. {mode conformance (required)}
8.1/2
  {AI95-00423-01} For a parameter or result subtype of a formal_subprogram_declaration that has an explicit null_exclusion:
8.2/2
8.3/2
8.a/2
Reason: This rule prevents “lying”. Null must never be the value of a parameter or result with an explicit null_exclusion. The first bullet is an assume-the-worst rule which prevents trouble in generic bodies (including bodies of child generics) when the formal subtype excludes null implicitly. 
8.4/2
  {AI95-00260-02} If a formal parameter of a formal_abstract_subprogram_declaration is of a specific tagged type T or of an anonymous access type designating a specific tagged type T, T is called a controlling type of the formal_abstract_subprogram_declaration. Similarly, if the result of a formal_abstract_subprogram_declaration for a function is of a specific tagged type T or of an anonymous access type designating a specific tagged type T, T is called a controlling type of the formal_abstract_subprogram_declaration. A formal_abstract_subprogram_declaration shall have exactly one controlling type. {controlling type (of a formal_abstract_subprogram_declaration)}
8.b/2
Ramification: The specific tagged type could be any of a formal tagged private type, a formal derived type, a formal interface type, or a normal tagged type. While the last case doesn't seem to be very useful, there isn't any good reason for disallowing it. This rule ensures that the operation is a dispatching operation of some type, and that we unambiguously know what that type is.
8.c/2
We informally call a subprogram declared by a formal_abstract_subprogram_declaration an abstract formal subprogram, but we do not use this term in normative wording. {abstract formal subprogram} (We do use it often in these notes.) 
8.5/2
  {AI95-00260-02} The actual subprogram for a formal_abstract_subprogram_declaration shall be a dispatching operation of the controlling type or of the actual type corresponding to the controlling type.
8.d/2
To be honest: We mean the controlling type of the formal_abstract_subprogram_declaration, of course. Saying that gets unwieldy and redundant (so says at least one reviewer, anyway). 
8.e/2
Ramification: This means that the actual is either a primitive operation of the controlling type, or an abstract formal subprogram. Also note that this prevents the controlling type from being class-wide (with one exception explained below), as only specific types have primitive operations (and a formal subprogram eventually has to have an actual that is a primitive of some type). This could happen in a case like: 
8.f/2
generic
   type T(<>) is tagged private;
   with procedure Foo (Obj : in T) is abstract;
package P ...
8.g/2
package New_P is new P (Something'Class, Some_Proc);
8.h/2
The instantiation here is always illegal, because Some_Proc could never be a primitive operation of Something'Class (there are no such operations). That's good, because we want calls to Foo always to be dispatching calls.
8.i/2
Since it is possible for a formal tagged type to be instantiated with a class-wide type, it is possible for the (real) controlling type to be class-wide in one unusual case:
8.j/2
generic
   type NT(<>) is new T with private;
   -- Presume that T has the following primitive operation:
   -- with procedure Bar (Obj : in T);
package Gr ...
8.k/2
package body Gr is
   package New_P2 is new P (NT, Foo => Bar);
end Gr;
8.l/2
package New_Gr is new Gr (Something'Class);
8.m/2
The instantiation of New_P2 is legal, since Bar is a dispatching operation of the actual type of the controlling type of the abstract formal subprogram Foo. This is not a problem, since the rules given in 12.5.1 explain how this routine dispatches even though its parameter is class-wide.
8.n/2
Note that this legality rule never needs to be rechecked in an instance (that contains a nested instantiation). The rule only talks about the actual type of the instantiation; it does not require looking further; if the actual type is in fact a formal type, we do not intend looking at the actual for that formal.

Static Semantics

9
A formal_subprogram_declaration declares a generic formal subprogram. The types of the formal parameters and result, if any, of the formal subprogram are those determined by the subtype_marks given in the formal_subprogram_declaration; however, independent of the particular subtypes that are denoted by the subtype_marks, the nominal subtypes of the formal parameters and result, if any, are defined to be nonstatic, and unconstrained if of an array type [(no applicable index constraint is provided in a call on a formal subprogram)]. In an instance, a formal_subprogram_declaration declares a view of the actual. The profile of this view takes its subtypes and calling convention from the original profile of the actual entity, while taking the formal parameter names and default_expressions from the profile given in the formal_subprogram_declaration. The view is a function or procedure, never an entry. 
9.a
Discussion: This rule is intended to be the same as the one for renamings-as-declarations, where the formal_subprogram_declaration is analogous to a renaming-as-declaration, and the actual is analogous to the renamed view. 
10
If a generic unit has a subprogram_default specified by a box, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a usage name identical to the defining name of the formal.
10.1/2
   {AI95-00348-01} If a generic unit has a subprogram_default specified by the reserved word null, and the corresponding actual parameter is omitted, then it is equivalent to an explicit actual parameter that is a null procedure having the profile given in the formal_subprogram_declaration.
10.2/2
   {AI95-00260-02} The subprogram declared by a formal_abstract_subprogram_declaration with a controlling type T is a dispatching operation of type T.
10.a.1/2
Reason: This is necessary to trigger all of the dispatching operation rules. It otherwise would not be considered a dispatching operation, as formal subprograms are never primitive operations. 
NOTES
11
13  The matching rules for formal subprograms state requirements that are similar to those applying to subprogram_renaming_declarations (see 8.5.4). In particular, the name of a parameter of the formal subprogram need not be the same as that of the corresponding parameter of the actual subprogram; similarly, for these parameters, default_expressions need not correspond.
12
14  The constraints that apply to a parameter of a formal subprogram are those of the corresponding formal parameter of the matching actual subprogram (not those implied by the corresponding subtype_mark in the _specification of the formal subprogram). A similar remark applies to the result of a function. Therefore, to avoid confusion, it is recommended that the name of a first subtype be used in any declaration of a formal subprogram.
13
15  The subtype specified for a formal parameter of a generic formal subprogram can be any visible subtype, including a generic formal subtype of the same generic_formal_part.
14
16  A formal subprogram is matched by an attribute of a type if the attribute is a function with a matching specification. An enumeration literal of a given type matches a parameterless formal function whose result type is the given type.
15
17  A default_name denotes an entity that is visible or directly visible at the place of the generic_declaration; a box used as a default is equivalent to a name that denotes an entity that is directly visible at the place of the _instantiation
15.a
Proof: Visibility and name resolution are applied to the equivalent explicit actual parameter. 
16/2
18  {AI95-00260-02} The actual subprogram cannot be abstract unless the formal subprogram is a formal_abstract_subprogram_declaration (see 3.9.3).
16.1/2
19  {AI95-00260-02} The subprogram declared by a formal_abstract_subprogram_declaration is an abstract subprogram. All calls on a subprogram declared by a formal_abstract_subprogram_declaration must be dispatching calls. See 3.9.3.
16.2/2
20  {AI95-00348-01} A null procedure as a subprogram default has convention Intrinsic (see 6.3.1). 
16.a.1/2
Proof: This is an implicitly declared subprogram, so it has convention Intrinsic as defined in 6.3.1. 

Examples

17
Examples of generic formal subprograms: 
18/2
{AI95-00433-01} with function "+"(X, Y : Item) return Item is <>;
with function Image(X : Enum) return String is Enum'Image;
with procedure Update is Default_Update;
with procedure Pre_Action(X : in Item) is null;  -- defaults to no action
with procedure Write(S    : not null access Root_Stream_Type'Class;
                     Desc : Descriptor)
                     is abstract Descriptor'Write;  -- see 13.13.2
-- Dispatching operation on Descriptor with default
19
--  given the generic procedure declaration 
20
generic
   with procedure Action (X : in Item);
procedure Iterate(Seq : in Item_Sequence);
21
--  and the procedure 
22
procedure Put_Item(X : in Item);
23
--  the following instantiation is possible 
24
procedure Put_List is new Iterate(Action => Put_Item);

Extensions to Ada 95

24.a/2
{AI95-00260-02} {extensions to Ada 95} The formal_abstract_subprogram_declaration is new. It allows the passing of dispatching operations to generic units.
24.b/2
{AI95-00348-01} The formal subprogram default of null is new. It allows the default of a generic procedure to do nothing, such as for passing a debugging routine. 

Wording Changes from Ada 95

24.c/2
{AI95-00423-01} Added matching rules for null_exclusions.

Table of Contents   Index   References   Search   Previous   Next 
Ada-Europe Sponsored by Ada-Europe