Version 1.1 of acs/ac-00060.txt

Unformatted version of acs/ac-00060.txt version 1.1
Other versions for file acs/ac-00060.txt

!standard C.8(01)          03-07-25 AC95-00060/01
!class amendment 03-07-22
!status received no action 03-07-22
!status received 03-04-14
!subject Relaxed freezing rules for generic instantiations

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


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.


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:

	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:

	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:

	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);
	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;


	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.


(See summary.)


(See summary.)


(See problem.)


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