Version 1.1 of ais/ai-00348.txt

Unformatted version of ais/ai-00348.txt version 1.1
Other versions for file ais/ai-00348.txt

!standard 6.07(00)          03-09-02 AI95-00348/01
!standard 3.01(09)
!standard 7.06(06)
!standard 7.06(08)
!standard 7.06(09)
!class amendment 03-09-02
!status work item 03-09-02
!status received 03-09-02
!priority Medium
!difficulty Easy
!subject Null procedures
!summary
This proposal adds "null procedures" to the standard.
A "null procedure" is a procedure declaration of the (newly introduced) form
procedure P (...) is null;
whose dynamic semantics are similar to a procedure with the body
procedure P (...) is begin null; end;
!problem
Null procedures are a prerequisite for AI-251 (abstract interfaces); see the discussion section below.
They would also be useful in the specification of Ada.Finalization.
!proposal
(See wording.)
! Wording
3.1 Declarations
Add to syntax (paragraph 3)
basic_declaration ::= ... | null_procedure_declaration
6.7 Null Procedures
Syntax
null_procedure_declaration ::= procedure_specification is null;
Static Semantics
A null_procedure_declaration declares a null procedure.
Dynamic Semantics
The execution of a null procedure is invoked by a subprogram call. The execution of the subprogram_body of a null procedure has no effect.
Replace 7.6(6) with
procedure Initialize (Object : in out Controlled) is null; procedure Adjust (Object : in out Controlled) is null; procedure Finalize (Object : in out Controlled) is null;
Replace 7.6(8) with
procedure Initialize (Object : in out Limited_Controlled) is null; procedure Finalize (Object : in out Limited_Controlled) is null;
Delete the second sentence of 7.6(9):
The (default) implementations of Initialize, Adjust, and Finalize have no effect.
!discussion
Like an instantiation, a null procedure is not allowed as a completion. Allowing this would double the amount of RM text needed for no real gain.
Like an instantiation, a null procedure does not "require completion".
A null procedure may have OUT-mode parameters, just as a "begin null; end;" procedure may. Note that copyback is performed in this case, just as for a "begin null; end;" procedure. The phrase "The execution of the subprogram_body" in the dynamic semantics section refers to 6.4(10)'s "The subprogram_body is then executed", which is just one of the steps in the execution of a subprogram call. The call as a whole may have a user-visible side-effect (e.g. trashing a scalar out parameter); it is only the "execution of the subprogram_body" step of the call which has no effect.
The proposed changes to Ada.Finalization are not an essential part of this AI.
Although the primary motivation for null procedures is for use with interface types (AI-251), they are also useful in other contexts. For code in a generic which always "passes the buck" to the corresponding parent primitive (as is done for Finalize, for example), the compiler can eliminate such a call when the parent's operation is known to be null at instantiation time. There are obvious documentation advantages for someone extending a type to know that the default implementation of an operation is null.
Null procedures make interface types much more useful.
The ability to declare a primitive of an interface as a null procedure enables existing abstract types that have null (non-abstract) default implementations of some of their primitives to be transitioned to being interface types. An example of such a type is Ada.Finalization.Controlled. [Note that there are other considerations which might argue for leaving Controlled as a "normal" tagged type, but the capability of switching other existing abstract tagged types to be interfaces remains potential quite useful, in our view.]
The ability to have non-dispatching calls on the primitive of a generic formal interface type to be made inside the generic can be necessary to enable a pass-the-buck-to-the-parent paradigm when overriding the operation. This is the paradigm used for finalization, for example, and is quite common in type hierarchies in general.
For example:
type T is interface; procedure Prim1(X : T) is null; procedure Prim2(X : T) is abstract;
generic type NT is abstract new T with private; -- NT guaranteed to have non-abstract implementation of Prim1 package P is type NN is new NT with private; procedure Prim1(X : NN); -- may "pass-the-buck" to Prim1 of NT as part -- of implementation of Prim1 of NN. procedure Prim2(X : NN); -- Prim2 must be overridden; -- cannot call Prim2 of NT since might be abstract end P;
--------
Null procedures are distinct subprograms in the sense of 4.5.2(13). This means that in this example
package Pkg1 is procedure P is null; end P1;
package Pkg2 is procedure P is null; end;
with Pkg1, Pkg2; package Pkg3 is type Ref is access procedure; Ptr1 : Ref := Pkg1.P'access; Ptr2 : Ref := Pkg2.P'access; Eq : constant Boolean := Ptr1 = Ptr2; end;
Eq must be False.
!example
package Pkg is procedure Proc is null; end Pkg;
--!corrigendum H.00(00)
!ACATS test
Test(s) need to be constructed.
!appendix

From: Stephen W Baird
Sent: Tuesday, September 2, 2003  4:01 PM

It was suggested at the Toulouse meeting that null procedures should be
defined in a separate AI, rather than as a part of AI-251 (interface
types). This is an initial version of that AI.

[This is version /01 of the AI.]

****************************************************************

From: Jean-Pierre Rosen
Sent: Wednesday, September 3, 2003  2:02 AM

This version does not address null procedures as default for generic formal
procedures
i.e.
generic
   with procedure P (...) is null;
package Gen ....

Is it an omission or a separate AI?

****************************************************************

From: Stephen W Baird
Sent: Wednesday, September 3, 2003 12:49 PM

I was trying to keep the proposal as simple as possible.

I didn't want to deal with, for example, the interactions between this new
kind of subprogram_default and equality operators for access-to-subprogram
types.

Defaults for formal subprogram parameters can currently only be used to
refer to already-existing subprograms. The change you mention would mean
that instantiating a generic would have the side effect of generating a
new subprogram for use as an actual parameter. It would violate the
correspondence between generic actual parameters and renames.

I'm not claiming that one should therefore conclude that this change is a
bad idea or that it could not be properly defined. I'm just saying that
it is more complicated than one might think at first glance and that I
chose to steer clear of that complexity.

If there is a general consensus in favor of this feature, I think it would
belong in this AI. In any case, it probably ought to be mentioned in the
discussion section.

****************************************************************

From: Tucker Taft
Sent: Wednesday, September 3, 2003  3:20 PM

It seems like a natural and quite useful generalization to allow
"is null" for formal procedures.  It certainly doesn't
require generating a "real" procedure for macro-expanded
generics, and for shared generics, the implementation
is presumably pretty used to generating "thunks"
for cases where the actual is a predefined operator,
attribute, etc.

So I would argue for its inclusion, sooner rather than later,
though I understand your desire to get the simpler version
out the door.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, September 3, 2003  4:00 PM

And we agreed to include it at the last meeting. So, I think it should be
included in the AI unless there is a pretty significant problem with it (in
which case, the problem ought to be discussed in the Discussion section).

****************************************************************


Questions? Ask the ACAA Technical Agent