CVS difference for ais/ai-00254.txt

Differences between 1.6 and version 1.7
Log of other versions for file ais/ai-00254.txt

--- ais/ai-00254.txt	2003/09/24 20:50:34	1.6
+++ ais/ai-00254.txt	2003/11/27 02:01:13	1.7
@@ -1,4 +1,4 @@
-!standard 03.10   (11)                               03-09-22  AI95-00254/04
+!standard 03.10   (11)                               03-11-11  AI95-00254/05
 !class amendment 00-12-06
 !status work item 02-11-06
 !status ARG Approved 5-0-2  02-02-11
@@ -6,93 +6,137 @@
 !status received 00-12-06
 !priority Low
 !difficulty Hard
-!subject Downward closures for access to subprogram types
+!subject Anonymous access to subprogram types
 
 !summary
 
-Access parameters are extended to include anonymous access-to-subprogram
-types. These enable an access to a subprogram at any level to be passed as
-an actual parameter.
+Anonymous access-to-subprogram types are introduced as possible forms of
+access parameters and in other contexts as well by analogy with anonymous
+access-to-object types. Such anonymous types increase the flexibility of
+manipulating an access to a subprogram and in particular allow an access to
+a subprogram at any level to be passed as an actual parameter to a subprogram.
 
 !problem
 
-Despite the improvements introduced in Ada 95, there is no still no
+Despite the improvements introduced in Ada 95, there is still no
 convenient way to perform certain general operations such as integration,
 minimization, iteration etc. where the operation has to be parameterized by
 a subprogram. This functionality was provided in Algol 60 and Pascal and it
-is surprising that it is not in Ada.
+is surprising that it is not in Ada. This is the main motivation for
+introducing anonymous access-to-subprogram types.
 
+Furthermore, experience with anonymous access-to-object types has shown that
+they are not as flexible as might have been desired and it is thus proposed
+that they by permitted in more contexts as described in AI-230 and with
+further control over whether they have a null value in AI-231. Similar
+flexibility is hereby proposed for anonymous access-to-subprogram types.
+
 !proposal
 
-Access parameters are extended to include anonymous access-to-subprogram types.
-The changes to the syntax are as follows
+NOTE: this AI assumes that AI-230 and AI-231 are approved. It is based on
+AI-230/07 and AI-231/05. Changes may be required if these AIs are modified.
 
-[NOTE: this assumes that AI-231 is approved and is based on version 04; if the
-changes approved to AI-231/04 by straw votes at Toulouse are confirmed then
-the syntax will need modifying to move not_null_constraint.]
+The key change is that the syntactic form access_definition which currently
+is used solely for anonymous access-to-object types is extended to include
+anonymous access-to-subprogram types. Thus
 
    access_definition ::=
-      access [all | constant] subtype mark [not_null_constraint] |
-      access procedure parameter_profile [not_null_constraint] |
-      access function parameter_and_result_profile [not_null_constraint]
+      [null_exclusion] access [general_access_modifier] subtype mark |
+      [null_exclusion] access procedure parameter_profile |
+      [null exclusion] access function parameter_and_result_profile
+
+Recall that AI-230 permits access_definition in contexts other than as formal
+parameters. We will first consider the use of anonymous access-to-subprogram
+types as formal parameters and then in other contexts.
+
+Consider
+
+function Integrate(Fn: access function(X: Float) return Float;
+                   Lo, Hi: Float) return Float;
 
 The actual subprogram corresponding to an anonymous access-to-subprogram
-parameter must be an access value designating a subprogram which is subtype
-conformant to the formal profile. If a not_null_constraint is supplied then
-the actual parameter must not be null (this is a runtime check).
-
-The only operations permitted on such a formal subprogram parameter are a)
-to call it, and b) to pass it as an actual parameter to another subprogram
-call. (This simple semantics avoids many implementation problems and
-parallels the functionality of the corresponding construction in languages
-such as Pascal.)
+parameter such as Fn must be an access value designating a subprogram which
+is subtype conformant to the formal profile. If a null_exclusion is supplied
+then the actual parameter must not be null (this is a runtime check).
 
+Thus we might have
+
+   function F(X: Float) return Float is
+   begin
+      return ...;
+   end F;
+
+   ... := Integrate(F'Access, 0.0, 1.0);
+
+The only operations permitted on a formal subprogram parameter such as Fn
+are a) to call it, b) to pass it as an actual parameter to another subprogram
+call, and c) to rename it, see below. (This simple semantics avoids many
+implementation problems and parallels the functionality of the corresponding
+construction in languages such as Pascal.)
+
 The accessibility level of such parameters is considered to be infinite.
 This prevents all explicit type conversions on such parameters. Moreover,
 since they are of anonymous type like access-to-object parameters this
 implies that assignment of them is forbidden. Note that the infinite
-accessibility level also prevents the writing of P.all'Access
+accessibility level also prevents the writing of Fn.all'Access
 which could otherwise create a hidden type conversion. (These restrictions
 again avoid a number of potential implementation difficulties.)
 
 Accessibility checks are never required and so such parameters do not need
-to carry an accessibility level with them.
+to carry an accessibility level with them in contrast to access-to-object
+parameters.
 
-Access-to-subprogram values may not be used as access discriminants.
+Default parameters are permitted for access-to-subprogram parameters with
+the usual semantics for parameters of mode in.
 
 The option of being protected does not apply to access-to-subprogram
 parameters. An access to a protected operation may not be passed to such
 parameters.
 
-Default parameters are permitted for access-to-subprogram parameters with
-the usual semantics for parameters of mode in.
-
 The convention of an access-to-subprogram parameter is the convention of the
-subprogram that contains the parameter. It cannot be changed by a pragma
-such as Convention.
-!wording
+subprogram that contains the parameter.
 
-Replace the second sentence of 3.7(9) by
+Anonymous access-to-subprogram types may also be used in other contexts by
+analogy with access-to-object types and in particular as extended by AI-230.
+These contexts are renamings, component definitions and discriminants.
 
-A discriminant that is defined by an access_definition is called an
-access_discriminant. The access definition shall designate an access-to-object
-type. The access disriminant is of an anonymous general access-to-object type
-whose designated subtype is denoted by the subtype_mark of the
-access_definition.
+In these other contexts, the infinite accessibility rule does not apply. They
+take the normal accessibility level as applied to access-to-object types.
 
-[NOTE: this prevents access-to-subprogram types as access discriminants.]
+Thus we might have
 
-Replace 3.10(6) by
+P: access function (F: Float)return Float renames Fn;
 
-   access_definition ::=
-      access [all | constant] subtype mark [not_null_constraint] |
-      access procedure parameter_profile [not_null_constraint] |
-      access function parameter_and_result_profile [not_null_constraint]
+Note that we are renaming the parameter which is an object, we are not
+renaming a subprogram per se. The accessibility level is inherited from the
+renamed object which might or might not be infinite.
+
+type R is
+   record
+      CP: access function(F: Float) return Float;
+   end record;
+
+A_Record: R := (Sqrt'Access);
+
+type A is array(Integer range <>) of access function(F: Float)return Float;
 
-[NOTE: this assumes AI-231/04 and will need modifying to conform to the
-final version of that AI.]
+An_Array: A := (Sqrt'Access, Sin'Access, Log'Access,...);
 
+type DR(D: access function(Integer) return Integer) is record ... end record;
 
+In all these situations subtype conformance is required.
+
+!wording
+
+This assumes the wording as already modified by AI-230/07 and AI-231/05.
+
+Replace 3.10(6) by
+
+   access_definition ::=
+      [null_exclusion] access [general_access_modifier] subtype mark |
+      [null_exclusion] access procedure parameter_profile |
+      [null exclusion] access function parameter_and_result_profile
+
 Replace 3.10(12) by
 
 An access_definition defines an anonymous general access type or an
@@ -103,22 +147,23 @@
 parameter_profile or parameter_and_result_profile denotes its designated
 profile.
 
-If a not_null_constraint is present, or the
+If a null_exclusion is present, or the
 access_definition is for a controlling access parameter (see 3.9.2), the
 access_definition defines an access subtype which excludes the null value;
 otherwise the subtype includes a null value. An access_definition is used
 in the specification of an access discriminant (see 3.7) or an access
-parameter (see 6.1). [NOTE: Modify this last sentence if AI-230 is approved.]
+parameter (see 6.1). [NOTE: Modify as finally decided by AI-230 either
+to delete the last sentence or add renaming and components.]
 
 Replace 3.10.2(13) by
 
 *   The accessibility level of the anonymous access type of an access
-    parameter specifiying an access-to-object type is the same as that
+    parameter specifying an access-to-object type is the same as that
     of the view designated by the actual. If the actual is an allocator,
     this is the accessibility level of the execution of the called subprogram.
 
 *   The accessibility level of the anonymous access type of an access parameter
-    specifiying an access-to-subprogram type is infinite.
+    specifying an access-to-subprogram type is infinite.
 
 [NOTE: I don't think anything else in this section needs changing. In
 particular, 3.10.2(32) seems OK still.]
@@ -127,16 +172,15 @@
 
 An access parameter is a formal in parameter specified by an access_definition.
 An access parameter is of an anonymous general access-to-object type or an
-aononymous access-to-subprogram type (see 3.10). Access parameters of an
+anonymous access-to-subprogram type (see 3.10). Access parameters of an
 access-to-object type allow dispatching calls to be controlled by access
 values. Access parameters of an access-to-subprogram type permit calls to
-subprograms passed as parameters irrespective of their accessibility level
-(commonly called downward closures).
+subprograms passed as parameters irrespective of their accessibility level.
 
 Replace 6.1(27) by
 
 *   For access parameters of an access-to-object type, the designated
-    subtype of the the parameter type.
+    subtype of the parameter type.
 
 *   For access parameters of an access-to-subprogram type, the subtypes of
     the profile of the parameter type.
@@ -144,8 +188,7 @@
 Add after 6.3.1(13)
 
 *   The calling convention for an access parameter of an access-to-subprogram
-    type is the convention of the subprogram that contains the parameter. It
-    shall not be overridden. [NOTE: despite 6.3.1(3)]
+    type is the convention of the subprogram that contains the parameter.
 
 [NOTE: 6.4.1(6) says
 
@@ -162,7 +205,9 @@
 integration, iteration and so on. The other use is where the subprogram is
 provided for return communication purposes (usually known as callback); the
 pointer is passed to some other program which later calls back to the
-client by calling the subprogram whose address was handed over.
+client by calling the subprogram whose address was handed over. A variation
+on this is where pointers to subprograms are held in data structures for
+later use.
 
 The first usage was familiar in older languages such as Algol and Pascal.
 The second usage was provided in newer languages such as C and Modula. Ada
@@ -178,7 +223,7 @@
 have been inappropriate to include either at the time of the design of Ada
 9X largely because of implementation difficulties for display-based
 implementations and for those with shared generics. It should be noted that
-it was recognised that there were workarounds involving generics and/or the
+it was recognized that there were workarounds involving generics and/or the
 new tagged types.
 
 The example in LSN 1083 concerns iterators. An example from the field of
@@ -219,7 +264,7 @@
 techniques that have evolved over the years.
 
 It is concluded (see the example) that the workarounds are not satisfactory
-and that Ada 0y should include the feature.
+and that Ada 2005 should include the feature.
 
 LSN 1083 suggested two mechanisms: limited access-to-subprogram types and
 access-to-subprogram-parameters. Of these, the second is preferred because
@@ -267,9 +312,16 @@
 assignment of access-to-subprogram parameters thereby greatly reducing the
 implementation burden, b) the workarounds are horrid and a continual
 embarrassment in a general purpose language, c) seemingly much bigger
-changes are being formulated for Ada 0y and it would not seem that much of
+changes are being formulated for Ada 2005 and it would not seem that much of
 a change to users but a relief.
 
+Finally it should be noted that further flexibility is being added for
+access types in general by AI-230 and AI-231. In particular anonymous
+access-to-object types are being permitted in contexts such as renaming
+and as components. For uniformity, similar flexibility is proposed for
+access-to-subprogram types. These follow automatically from the few
+general wording changes concerning the syntactic item access_definition.
+
 ============== LSN 1083 (slightly condensed extracts)
 
 1  Background to Downward Closures:
@@ -491,7 +543,7 @@
 difficulties are then encountered.
 
 A good practical example is provided by a double integral where the function
-to be integrated is itself the result of an integration. Supose we wish to
+to be integrated is itself the result of an integration. Suppose we wish to
 compute the integral of the product xy over the square region [0, 1],[0, 1].
 We can pose this as the result of integrating the function G(x) between 0 and
 1 where the value of G(x) is the result of integrating the function F(y)
@@ -654,26 +706,35 @@
 to pass any auxiliary data such as the nonlocal variable X.
 
 with Integrate;
-procedure Main is
+ppackage P is
+
+   type F_Integrator is new Integrate.Integrator with
+      record
+         X_Copy: Float;
+      end record;
+   function Integrand(Y: Float: Int: F_Integrator) return Float;
+
    type G_Integrator is new Integrate.Integrator with null record;
-   Int_G: G_Integrator;
+   function Integrand(X: Float: Int: G_Integrator) return Float;
+end P;
+
+package body P is
 
+   function Integrand(Y: Float: Int: F_Integrator) return Float is
+   begin
+      return Int.X_Copy*Y;
+   end Integrand;
+
    function Integrand(X: Float: Int: G_Integrator) return Float is
-      type F_Integrator is new Integrate.Integrator with
-         record
-            X_Copy: Float;
-         end record;
       Int_F: F_Integrator;
-
-      function Integrand(Y: Float: Int: F_Integrator) return Float is
-      begin
-         return Int.X_Copy*Y;
-      end F;
    begin
       Int_F.X_Copy := X;
       return Integrate.Do_It(Int_F, 0.0, 1.0);
-   end G;
+   end Integrand;
 
+with Integrate, P;
+procedure Main is
+   Int_G: P.G_Integrator;
    Result: Float;
 begin
    Result := Integrate.Do_It(Int_G, 0.0, 1.0);
@@ -682,16 +743,16 @@
 
 The above will work and is flexible and does not involve generics. However,
 by no stretch of the imagination can it be considered natural or elegant. It
-is probably the case that typical programmers can only use this technique by
-copying an example from a textbook. It therefore fails as an acceptable
-workaround.
+is absolutely disgusting. It is probably the case that typical programmers
+can only use this technique by copying an example from a textbook. It
+therefore fails as an acceptable workaround.
 
 The proposed solution using access-to-subprogram parameters is as follows.
 The integrate package now becomes
 
 package Integrate is
    function Do_It(Fn: access function(X: Float) return Float;
-                  Lo, Hi: Float);
+                  Lo, Hi: Float) return Float;
 end;
 
 Note that the function Do_It now has an access-to-subprogram parameter. The
@@ -802,7 +863,7 @@
 !reference RM9X-3.10.2(16);4.0
 !reference AARM-12.3(12.p,12.q);4.0
 !reference LSN-1042 on Accessibility Checks in Generics
-!from Bob Duff $Date: 2003/09/24 20:50:34 $ $Revision: 1.6 $
+!from Bob Duff $Date: 2003/11/27 02:01:13 $ $Revision: 1.7 $
 !discussion
 
 Two issues related to access types and the accessibility rules came
@@ -1162,7 +1223,7 @@
 
 One problem with either solution is that there is a substantial
 implementation burden for implementations that do universal generic
-code sharing.  For such implementions, when a subprogram declared
+code sharing.  For such implementations, when a subprogram declared
 inside the generic unit is called, it needs to be implicitly passed
 an extra parameter that represents the current instance.  This extra
 parameter is used by the subprogram to address variables declared in
@@ -1215,7 +1276,7 @@
 !topic LSN on Accessibility Checks in Generics
 !key LSN-1042 on Accessibility Checks in Generics
 !reference MS-12;4.6
-!from Bob Duff $Date: 2003/09/24 20:50:34 $ $Revision: 1.6 $
+!from Bob Duff $Date: 2003/11/27 02:01:13 $ $Revision: 1.7 $
 !discussion
 
 This Language Study Note discusses accessibility checks, and their
@@ -1326,7 +1387,7 @@
 
 > One problem with either solution is that there is a substantial
 > implementation burden for implementations that do universal generic
-> code sharing.  For such implementions, when a subprogram declared
+> code sharing.  For such implementations, when a subprogram declared
 > inside the generic unit is called, it needs to be implicitly passed
 > an extra parameter that represents the current instance.  This extra
 > parameter is used by the subprogram to address variables declared in
@@ -1416,7 +1477,7 @@
 
 Modula-2 has pointer-to-procedure types, but they can't point to nested
 procedures.  This is essentially the same restriction we have in Ada
-with the acessibility rules: you can't pass a nested procedure as a
+with the accessibility rules: you can't pass a nested procedure as a
 parameter to an outer procedure.
 
 I haven't read the paper, so I don't know if their technique requires
@@ -1428,11 +1489,11 @@
 Sent: Monday, November 06, 2000 9:43 AM
 
 I suppose we could dig up the old proposals in this area. I must say that
-if the strongest argument is alledged "bad press" I find that very weak.
+if the strongest argument is alleged "bad press" I find that very weak.
 What would be convincing would be real customer experience. We have not
 had any demands in the GNAT community, but that may be deceptive because
 of the availability of Urestricted_Access in GNAT -- which indeed is
-very usefiul, and which we use ourselves and find critically important.
+very useful, and which we use ourselves and find critically important.
 
 ****************************************************************
 
@@ -1445,7 +1506,7 @@
 to deprive the majority of users of an important and natural feature because
 of a minority difficulty.>>
 
-Are you sure? I was under the impressoin that *all* Aonix compilers still
+Are you sure? I was under the impression that *all* Aonix compilers still
 used displays. Now I am the first to say that if you take all users of
 GNAT into use including the public version, then probably the statement
 is strictly true, and that Aonix users are in the minority, but this is
@@ -1459,7 +1520,7 @@
 From: Pascal Leroy
 Sent: Wednesday, August 29, 2001 7:55 AM
 
-> Are you sure? I was under the impressoin that *all* Aonix compilers still
+> Are you sure? I was under the impression that *all* Aonix compilers still
 > used displays.
 
 The old (Ada 83) Aonix technology surely used displays, but I thought that
@@ -1506,7 +1567,7 @@
 From: Tucker Taft
 Sent: Wednesday, August 29, 2001 8:57 AM
 
-> > Are you sure? I was under the impressoin that *all* Aonix compilers still
+> > Are you sure? I was under the impression that *all* Aonix compilers still
 > > used displays.
 >
 > The old (Ada 83) Aonix technology surely used displays, but I thought that
@@ -1548,7 +1609,7 @@
 of giving up shared-body generics, but if the proposal is to jettison
 shared-body generics, (rather than accommodating them somehow), then
 that should be explicitly stated.  And if so, various other accommodations
-in the language for shared-body generics should probably be be eliminated,
+in the language for shared-body generics should probably be eliminated,
 and class-wide untagged types should probably be added in lieu of
 shared-body generics.
 
@@ -1917,7 +1978,7 @@
 up with an alternative design that did not make use of
 generics (and did not have this memory cost...)
 
-There are a few Ada optmizations that can have substantial
+There are a few Ada optimizations that can have substantial
 impact on how you design your software.  Code sharing on
 generics and passive task optimizations are two that come
 to mind.  Without such optimizations, designers would
@@ -2248,7 +2309,7 @@
 From: Robert Dewar
 Sent: Friday, August 31, 2001  6:54 PM
 
-I disagree that it is a significant advantage to avoid recompilaion when
+I disagree that it is a significant advantage to avoid recompilation when
 bodies change. The motivation for generic sharing that is convincing is
 saving space. Speeding up compilation is an entirely secondary concern.
 
@@ -2518,7 +2579,7 @@
 patented by DEC a decade later (;-).
 
 In any case, clearly part of the problem is that there are few people on
-earth who understand the impliciations of doing "universal"
+earth who understand the implications of doing "universal"
 generic sharing, and when the AI author is not one of those
 few people, attempts to analyze the impact on universal
 generic sharing are difficult if not impossible.
@@ -2666,7 +2727,7 @@
 but latterly I have felt that it is really a bizarre approach. It seems
 unnatural and, as I hope the example in the AI demonstrates, the distortion
 is now placed on the user which in many ways is worse since it forces all users
-to visibly distort their prograsm whereas with optimizations it is partly
+to visibly distort their programs whereas with optimizations it is partly
 hidden by the implementation.
 
 It is of course unfortunate that the original absence of full procedure
@@ -2701,11 +2762,11 @@
 on implementers because the structural implications were restricted to a
 smallish part of the implementation.>>
 
-Speakoing for GNAT, the implementation of protected types was a major
+Speaking for GNAT, the implementation of protected types was a major
 development effort, and it is by no means complete, in terms of
 specialized optimizations that we would like to do.
 
-So if the judgment is that downward closures are anythying like that
+So if the judgment is that downward closures are anything like that
 big a hit, I would judge the addition out of the question.
 
 ****************************************************************
@@ -2762,7 +2823,7 @@
 optimizations. This is the point that Paul Hilfinger made during
 the design process. After all several vendors implemented passive
 task optimizations quite effectively, and indeed we find several
-customers who really miss passive task optimziations, and find
+customers who really miss passive task optimizations, and find
 protected types only a partially satisfactory substitute.
 
 ****************************************************************
@@ -2787,7 +2848,7 @@
 Ada 83 made people believe that passive task optimizations
 were the answer.  For example, we knew that allowing 'Count
 in barrier expressions would require up to three evaluations of
-the barrier for a protected entry call (before queueing,
+the barrier for a protected entry call (before queuing,
 after queuing, and after completion of the protected body),
 but it was argued that optimizations would eliminate this
 overhead in important cases.  Similarly with the need to
@@ -3064,7 +3125,7 @@
 algebraic equations. I turned to Ada, my favourite language
 for hacking such things. I quickly knocked up a general
 Newton-Raphson thing hoping that it would be simple enough
-to pass the functions to be solved as as access-to-function
+to pass the functions to be solved as access-to-function
 taking a vector and returning a vector. But I immediately
 fell into the downward closures pit. I had to make a lot of
 stuff global that shouldn't have been. In fact I ended up

Questions? Ask the ACAA Technical Agent