CVS difference for ai12s/ai12-0189-1.txt

Differences between 1.8 and version 1.9
Log of other versions for file ai12s/ai12-0189-1.txt

--- ai12s/ai12-0189-1.txt	2017/10/12 03:22:37	1.8
+++ ai12s/ai12-0189-1.txt	2018/03/29 06:04:33	1.9
@@ -1,4 +1,4 @@
-!standard 5.5(3/3)                                    17-10-11  AI12-0189-1/04
+!standard 5.5(3/3)                                    18-03-34  AI12-0189-1/05
 !standard 5.5.3(0)
 !class Amendment 16-06-02
 !status work item 16-06-02
@@ -74,13 +74,15 @@
 being specified as <>.
 
 An exit, return, goto, or other transfer of control out of the loop is
-allowed.  Such a transfer of control causes the named procedure to which
-the loop-body procedure is passed to be completed and left
-[Redundant(resulting in normal finalization)], followed by a transfer of
-control to the target of the original transfer of control that was
-within the loop.  The procedure calling the loop-body procedure must use
-finalization if it wants to perform any "last wishes" when the loop body
-procedure exits prematurely via a transfer of control.
+allowed if the named procedure has a True Allows_Exit aspect. Such a
+transfer of control causes the named procedure to which the loop-body
+procedure is passed to be completed and left [Redundant(resulting in
+normal finalization)], followed by a transfer of control to the target
+of the original transfer of control that was within the loop. A
+procedure with Allows_Exit specified True, when calling the loop-body
+procedure, must use finalization if it wants to perform any "last
+wishes" when the loop body procedure exits prematurely via a transfer of
+control.
 
 Implementation Note
 
@@ -94,6 +96,61 @@
 access-to-procedure value.  That could presumably make it simpler and
 safer than ATC.
 
+If we presume this is implemented using an exception-like thing which
+is *not* caught by "when others" (similar to how many implementations
+implement abort), then one would expect the loop-body procedure to
+set the value of some global variable to record the action to be taken
+when this special exception is propagated out of the named iterator
+procedure.  For example:
+
+   for (Name, Val) of Ada.Environment_Variables.Iterate loop
+      if Name = "good" then
+         Found := True;
+         exit;
+      elsif Name = "bad" then
+         raise Very_Bad_News;
+      end if;
+   end loop;
+
+   --  The above is equivalent to, presuming Iterate has Allows_Exit True
+   --  and the implementation uses a special "_exit_exception"
+
+   declare
+      _exit_action : Natural range 0 .. 2 := 0;
+      _exit_exception_occurrence : Exceptions.Exception_Occurrence;
+      procedure _loop_body (Name : String; Val : String) is
+      begin
+         if Name = "cool" then
+            Found := True;
+            _exit_action := 1;
+            raise _exit_exception;
+         elsif Name = "bad" then
+            raise Very_Bad_News;  -- all exceptions are handled below
+         end if;
+      when E:others =>
+         --  Catch any exceptions (other than _exit_exception!)
+         _exit_action := 2;
+         Exceptions.Save_Occurrence (_exit_occurrence, Source => E);
+         raise _exit_exception;
+      end _loop_body;
+   begin
+      Ada.Environment_Variables.Iterate (_loop_body'Access);
+   exception
+      when _exit_exception =>
+         case _exit_action is
+         when 0 => raise Program_Error;  --  Should not happen
+         when 1 => null; --  this is a simple exit
+         when 2 => Exceptions.Reraise_Occurrence(_exit_occurrence);
+                     -- propagate any exceptions
+   end;
+
+When Allows_Exit is False, then the loop can still end prematurely
+due to the propagation of an exception.  In this case, the
+implementation should simply propagate the exception from the loop body
+procedure into the Iterate procedure, whereas when Allows_Exit is True,
+the implementation should insert a handler surrounding the loop body
+when constructing the loop-body procedure, as illustrated above.
+
 !wording
 
 Modify 5.5(3/3):
@@ -139,18 +196,18 @@
 
      Name Resolution Rules
 
-The name or prefix given in an iterator_procedure_call shall resolve to denote a
-callable entity C that is a procedure, or an entry renamed as (viewed as) a
-procedure. The name or prefix shall not resolve to denote an abstract subprogram
-unless it is also a dispatching subprogram. [Redundant: When there is an
-iterator_actual_parameter_part, the prefix can be an implicit_dereference of an
-access-to-subprogram value.]
+The name or prefix given in an iterator_procedure_call shall resolve to
+denote a callable entity C that is a procedure, or an entry renamed as
+(viewed as) a procedure. The name or prefix shall not resolve to denote
+an abstract subprogram unless it is also a dispatching subprogram.
+[Redundant: When there is an iterator_actual_parameter_part, the prefix
+can be an implicit_dereference of an access-to-subprogram value.]
 
 An iterator_procedure_call without a parameter_association_with_box is
-equivalent to one with an iterator_actual_parameter_part with an additional
-parameter_association_with_box at the end, with the
-formal_parameter_selector_name identifying the last formal parameter of the
-callable entity denoted by the name or prefix.
+equivalent to one with an iterator_actual_parameter_part with an
+additional parameter_association_with_box at the end, with the
+formal_parameter_selector_name identifying the last formal parameter of
+the callable entity denoted by the name or prefix.
 
 An iterator_procedure_call shall contain at most one
 iterator_parameter_association for each formal parameter of the callable entity
@@ -172,40 +229,45 @@
 
      Static Semantics
 
-A loop_statement with an iteration_scheme that has a procedural_iterator is
-equivalent to a local declaration of a procedure P followed by a
-procedure_call_statement that is formed from the iterator_procedure_call by
-replacing the <> of the parameter_association_with_box with P'Access.  The
-formal_part of the locally declared procedure P is formed from the formal_part
-of the anonymous access-to-procedure type /A/, by replacing the identifier of
-each formal parameter of this formal_part with the identifier of the
-corresponding formal parameter or element of the list of identifiers given in
-the iterator_parameter_specification.
-
-The following aspect may be specified for a subprogram or entry S that has at
-least one formal parameter of an anonymous access-to-subprogram type:
-
-Exit_Exception
-   This aspect is specified by a name that denotes an exception E, or by
-   the literal NULL.  If not the literal NULL, this indicates that the
-   subprogram or entry S will terminate its execution and propagate the
-   exception E if E is propagated by an invocation of
-   a procedure denoted by a formal parameter of S having an anonymous
-   access-to-subprogram type.  The Exit_Exception of an inherited
-   primitive subprogram is that of the corresponding subprogram of the
-   progenitor type.  If not specified or inherited, the Exit_Exception aspect
-   of a subprogram or entry is the NULL literal.
+A loop_statement with an iteration_scheme that has a procedural_iterator
+is equivalent to a local declaration of a procedure P followed by a
+procedure_call_statement that is formed from the iterator_procedure_call
+by replacing the <> of the parameter_association_with_box with P'Access.
+ The formal_part of the locally declared procedure P is formed from the
+formal_part of the anonymous access-to-procedure type /A/, by replacing
+the identifier of each formal parameter of this formal_part with the
+identifier of the corresponding formal parameter or element of the list
+of identifiers given in the iterator_parameter_specification.
+
+The following aspect may be specified for a subprogram or entry S that
+has at least one formal parameter of an anonymous access-to-subprogram
+type:
+
+Allows_Exit
+   The Allows_Exit aspect is of type Boolean.  The specified value shall
+   be static.  The Allows_Exit of an inherited primitive subprogram is
+   True if Allows_Exit is True either for the corresponding subprogram
+   of the progenitor type or for any other inherited subprogram that it
+   overrides.  If not specified or inherited as True, the Allows_Exit
+   aspect of a subprogram or entry is False.
 
        Legality Rules
 
-If a subprogram or entry overrides an inherited subprogram that has an
-Exit_Exception aspect that is not the NULL literal, it shall specify the same
-exception for its Exit_Exception aspect.
-
-The sequence_of_statements of a loop_statement with a procedural_iterator as its
-iteration_scheme shall contain an exit_statement, return statement,
-goto_statement, or requeue_statement that leaves the loop only if the callable
-entity C has an Exit_Exception aspect that is not the NULL literal.
+If a subprogram or entry overrides an inherited dispatching subprogram
+that has a True Allows_Exit aspect, only a confirming specification of
+True is permitted for the aspect on the overriding declaration.
+
+The sequence_of_statements of a loop_statement with a
+procedural_iterator as its iteration_scheme shall contain an
+exit_statement, return statement, goto_statement, or requeue_statement
+that leaves the loop only if the callable entity C has an Allows_Exit
+aspect specified True.
+
+The sequence_of_statements of a loop_statement with a
+procedural_iterator as its iteration_scheme shall contain an
+exit_statement, return statement, goto_statement, or requeue_statement
+that leaves the loop only if the callable entity C has an Allows_Exit
+aspect specified True.
 
     Examples
 
@@ -309,11 +371,27 @@
 
 We considered various implementation approaches for handling a transfer
 of control from the loop body, including the notion of a "private"
-exception which was not handled by "others."  We ultimately decided to add an
-aspect Exit_Exception, that is required to be non null on the iterating
-procedure if you wish to perform a transfer of control.  The intent is that the
-compiler will raise and handle this exception to implement exit, goto, requeue,
-and return.
+exception which was not handled by "others." We ultimately decided to
+allow exit/return/etc. only if the Allows_Exit aspect is specified True
+on the iterator procedure, and then presume that a mechanism analogous
+to abort or ATC would be used, meaning that the iterator procedure will
+need to rely on finalization to do any cleanup in such a case.  See the
+Implementation Note above in the !proposal section.
+
+One concern is that this mechanism might be misused, since there is no
+requirement that the iterator procedure actually call the loop-body
+procedure more than once.  This was debated, but ultimately it was concluded
+that this does not interfere with its usefulness in the very common case
+of iteration, and individual projects can decide whether they choose to use
+this feature for non-iterating operations that take anonymous procedures.
+Our sense is that there are few compelling examples of use of anonymous
+procedures when no iteration is involved.
+
+One alternative would be to use "do ... end do" rather than "loop ... end loop"
+for this construct.  If the "do ... end do" syntax is ultimately adopted
+for the parallel block construct, then this might be an alternative worth
+considering, as it eliminates the implication that a loop is being performed
+(unless you are from the Fortran world where "do" means "loop" ;-).
 
 !ASIS
 
@@ -1969,5 +2047,14 @@
 
 And thanks for changing the model to something that doesn't give me indigestion
 each time I think about it.
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Saturday, March 24, 2018  2:57 PM
+
+Here is a modest update to the "loop-body" procedure proposal, consistent with
+the minutes from our last discussion of the AI. [This is version /05 of the
+AI - ED]
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent