Version 1.1 of ais/ai-00359.txt

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

!standard 13.14 (05)          03-07-25 AI95-00369/01
!class amendment 03-07-22
!status work item 03-09-29
!status received no action 03-07-22
!status received 03-04-14
!priority Low
!difficulty Medium
!subject Relaxed freezing rules for generic instantiations
!summary
To better support generic signature packages, and mutually dependent types that involve generic instantiations, it is proposed that a generic instantiation not cause freezing immediately if any of its actual parameters are types that have not been completely defined.
For such an instantiation, no special freezing happens at the point of the instantiation, other than the freezing that is due to the elaboration of the declarations within the "spec" of the instantiation. Elaboration of the body of the instantiation is deferred until a "general" freezing point occurs, which occurs at the end of the enclosing library unit or declarative part, upon encountering a "real" body, etc.
NOTE: This more "relaxed" freezing and deferred body elaboration could be used for all generic instantiations, but that could create some incompatibilities, since we would be altering the point when the body of the instantiation was elaborated. This proposal is guaranteed to be upward compatible, since only instantiations that are currently illegal would be using "relaxed" freezing and deferred body elaboration.
!problem
Ada 95 provides formal package parameters. One way of using these parameters is to define a "signature" for a class of abstractions, such as all set abstractions, or all physical unit abstractions, and then build a new generic abstraction on top of the original class of abstractions using this signature as the template for a formal package parameter.
Unfortunately, it is difficult to use signatures because of the fact that an instantiation freezes all of its actual parameters.
For example:
Given the signature for a set abstraction:
generic type Element is private; type Set is private; with function Size(Of_Set : Set) return Natural is <>; with function Union(Left, Right : Set) return Set is <>; with function Intersection(Left, Right : Set) return Set is <>; with function Empty return Set is <>; with function Unit_Set(With_Item : Element) return Set is <>; with function Nth_Element(Of_Set : Set) return Element is <>; package Set_Signature is end;
... we could define a generic that required some set abstraction, but it didn't care which one so long as it implemented the above signature:
generic with package Base_Set is new Set_Signature(<>); package Layered_Abstraction is type Cool_Type(Set : access Base_Set.Set) is limited_private; procedure Massage(CT : in out Cool_Type; New_Set : Base_Set.Set); ...
end Layered_Abstraction;
Now if we want to define a set type and provide the pre-instantiated signature for it, we run into trouble:
generic type Elem is private; with function Hash(El : Elem) return Integer; package Hashed_Sets is type Set is private; function Union(Left, Right : Set) return Set;
...
package Signature is new Set_Signature(Elem, Set); private type Set is record
... end record; end Hashed_Sets;
The problem is that we can't do the instantiation of Set_Signature where we would want to do so, because the instantiation freezes the type "Set" prematurely.
[For an extended example of use of signatures, see the physical units AI (AI-00324).]
A similar problem occurs when a type wants to include a pointer to a container based on the type being defined. For example:
package Expressions is type Expr_Ref is private;
package Expr_Sequences is new Sequences(Expr_Ref); -- Freezing trouble here! type Seq_Of_Expr is access Expr_Sequences.Sequence;
function Operands(Expr : Expr_Ref) return Seq_Of_Expr;
...
private type Expression; -- completion deferred to body type Expr_Ref is access Expression;
end Expressions;
Here we have a case where we want to instantiate a generic using a private type, and use the results of the instantiation as the designated type of an access type, which is in turn used as a parameter or result type of an operation on the private type.
Unfortunately, we can't instantiate the "Sequences" generic with Expr_Ref, since it is private.
!proposal
(See summary.)
!wording
(See summary.)
!example
(See problem.)
!discussion
Signature packages can be a very useful feature, but if they can't be instantiated in the generic that defines the abstraction, they become of much less use.
Generics in general can be very useful, but the freezing rules mean that they are not as powerful as cut-and-paste, since they can't be applied to private types before the private type is completely defined.
This proposal makes it possible for a generic instantiation to be used in more places than before, since it can be used with a private type before the type is completely defined. As things stand now, it is often necessary to completely restructure things to be able to use a generic container as part of defining a private type.
--!corrigendum 13.14(05)
!ACATS test
An ACATS test should be created for this pragma.
!summary
!appendix

From: Tucker Taft
Sent: Wednesday, February 12, 2003  5:50 PM

I talked about this AI a bit with Pascal in Padua.
Here is a first cut at it.  The basic idea is to
relax the freezing rules associated with generic
instantiations, so signatures can actually be used
in a reasonable way.

---

!standard 13.14     (05)           03-02-12  AI95-<<melting_instantiations>>/01
!class amendment 03-02-12
!status work item 03-02-12
!status received 03-02-12
!priority Medium
!difficulty Medium
!subject Deferring Freezing of a Generic Instantiation

!summary

To better support generic signature packages, and
mutually dependent types that involve generic instantiations,
it is proposed that a generic instantiation not cause
freezing immediately if any of its actual parameters
are types that have not been completely defined.

For such an instantiation, no special freezing happens
at the point of the instantiation, other than the freezing
that is due to the elaboration of the declarations within
the "spec" of the instantiation.   Elaboration of the body
of the instantiation is deferred until a "general" freezing
point occurs, which occurs at the end of the enclosing
library unit or declarative part, upon encountering a "real" body, etc.

NOTE: This more "relaxed" freezing and deferred body elaboration
could be used for all generic instantiations, but that could
create some incompatibilities, since we would be altering
the point when the body of the instantiation was elaborated.
This proposal is guaranteed to be upward compatible, since
only instantiations that are currently illegal would be
using "relaxed" freezing and deferred body elaboration.

!problem

Ada 95 provides formal package parameters.  One way of using
these parameters is to define a "signature" for a class of abstractions,
such as all set abstractions, or all physical unit abstractions, and
then build a new generic abstraction on top of the original
class of abstractions using this signature as the template for
a formal package parameter.

Unfortunately, it is difficult to use signatures because
of the fact that an instantiation freezes all of its
actual parameters.

For example:

  Given the signature for a set abstraction:

    generic
	type Element is private;
	type Set is private;
	with function Size(Of_Set : Set) return Natural is <>;
	with function Union(Left, Right : Set) return Set is <>;
	with function Intersection(Left, Right : Set) return Set is <>;
	with function Empty return Set is <>;
	with function Unit_Set(With_Item : Element) return Set is <>;
	with function Nth_Element(Of_Set : Set) return Element is <>;
    package Set_Signature is end;

  ... we could define a generic that required some set
  abstraction, but it didn't care which one so long
  as it implemented the above signature:

    generic
	with package Base_Set is new Set_Signature(<>);
    package Layered_Abstraction is
	type Cool_Type(Set : access Base_Set.Set) is limited_private;
	procedure Massage(CT : in out Cool_Type; New_Set : Base_Set.Set);
        ...

    end Layered_Abstraction;

  Now if we want to define a set type and provide the pre-instantiated
  signature for it, we run into trouble:

    generic
	type Elem is private;
	with function Hash(El : Elem) return Integer;
    package Hashed_Sets is
	type Set is private;
	function Union(Left, Right : Set) return Set;
	...

	package Signature is new Set_Signature(Elem, Set);
    private
	type Set is record
	   ...
	end record;
    end Hashed_Sets;

The problem is that we can't do the instantiation of Set_Signature
where we would want to do so, because the instantiation freezes
the type "Set" prematurely.

[For an extended example of use of signatures, see the physical
units AI (AI-00324).]

A similar problem occurs when a type wants to include a pointer
to a container based on the type being defined.  For example:

    package Expressions is
	type Expr_Ref is private;

	package Expr_Sequences is new Sequences(Expr_Ref);
	    -- Freezing trouble here!
	type Seq_Of_Expr is access Expr_Sequences.Sequence;

	function Operands(Expr : Expr_Ref) return Seq_Of_Expr;

	...

   private
	type Expression;  -- completion deferred to body
	type Expr_Ref is access Expression;

   end Expressions;

Here we have a case where we want to instantiate a generic
using a private type, and use the results of the instantiation
as the designated type of an access type, which is in turn
used as a parameter or result type of an operation on the
private type.

Unfortunately, we can't instantiate the "Sequences" generic
with Expr_Ref, since it is private.

!proposal

(See summary.)

!wording

(See summary.)

!example

(See problem.)

!discussion

Signature packages can be a very useful feature, but
if they can't be instantiated in the generic that defines
the abstraction, they become of much less use.

Generics in general can be very useful, but the freezing
rules mean that they are not as powerful as cut-and-paste,
since they can't be applied to private types before
the private type is completely defined.

This proposal makes it possible for a generic instantiation
to be used in more places than before, since it can
be used with a private type before the type is completely
defined.  As things stand now, it is often necessary to
completely restructure things to be able to use a generic
container as part of defining a private type.

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

From: Robert A Duff
Sent: Wednesday, February 12, 2003  7:09 PM

As a user of Ada, I would find this relaxation of the freezing rules to
be of *huge* benefit.

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


Questions? Ask the ACAA Technical Agent