CVS difference for ai12s/ai12-0197-4.txt

Differences between 1.1 and version 1.2
Log of other versions for file ai12s/ai12-0197-4.txt

--- ai12s/ai12-0197-4.txt	2016/12/28 03:16:21	1.1
+++ ai12s/ai12-0197-4.txt	2017/10/12 00:42:19	1.2
@@ -1,4 +1,4 @@
-!standard 9.11(0)                                    16-12-27  AI12-0197-4/00
+!standard 9.11(0)                                    17-10-11  AI12-0197-4/01
 !class Amendment 16-12-27
 !status work item 16-12-27
 !status received 16-10-20
@@ -7,7 +7,9 @@
 !subject Coroutines and channels
 !summary
 
-** TBD.
+'Yield and 'Consume attributes are added to the language. Exit statements 
+are allowed in a do statement, and implicity declared channels are defined
+for do statements.
 
 !problem
 
@@ -40,26 +42,168 @@
    iterators.
 
 !proposal
-
-We introduce coroutines and channels.
 
-A coroutine uses the same syntax and most semantics as a parallel block, but
+A coroutine uses the same syntax as a concurrent block, but
 the "arms" of the block are executed one at a time. Each of the arms can
-communicate using a special data structure called a channel; a read or write
+communicate using an implicit data structure called a channel; a read or write
 on a channel causes the current "arm" to stop executing and another "arm"
 starts/continues execution. An "arm" blocked on the read of a channel will
-continue once data is written to the channel by another "arm". ** More of this
-drivel is needed. :-) **
+continue once data is written to the channel by another "arm".
 
-** Rest TBD **
+This AI is dependent on AI12-0119-1 parallel operations.
 
-!wording
+Note that with just the capabilities of AI12-0119 we can already write
+coroutines;
 
-** TBD.
+e.g. Using an instantiation of Ada.Containers.Synchronous_Queuees, one
+could write;
+
+declare
+  Queue : Integer_Queues.Queue;
+begin
+
+   do
+      declare
+         X : Integer := 0;
+      begin
+         loop    -- endless loop
+            Integer_Queue.Enqueue (X);
+            X := X + 1;
+         end loop;
+      end;
+
+   and
+
+      for I in 1 .. 3 loop
+         Integer_Queue.Enqueue (1_000_000 + I);
+      end loop;
+
+   and
+
+      declare
+         Value : Integer;
+      begin
+         for I in 1 .. 5 loop
+            Integer_Queue.Dequeue (Value);
+            Put_Line ("Value=" & Integer'Image (Value));
+         end loop;
+
+         goto Done; -- or raise exception???
+      end;
+
+   end do; 
+
+   <<Done>>
+   
+Where the first two arms of the concurrent block are producing values
+for the third arm which is the consumer. Note that the first arm is
+actually an endless loop, which is a common idiom for generators in other
+languages. When the third arm exits the concurrent do statement via a
+transfer of control using the goto statement, the other arms of the
+generator are terminated, and the construct is left, as described in
+AI12-0119.
+
+All three arms execute concurrently within the same processor as the
+enclosing task.
+
+However, we would like to not have to use queue abstractions, and 
+simplify this so that it is requires less effort to write coroutines,
+and allows the compiler to potentially substitute the code with a 
+lighter-weight implementation.
+
+To allow this, we define two new attributes that can be applied to a
+subtype;
+
+'Yield, and 'Consume.
+
+To generate a value, the 'Yield attribute may be used which writes a
+value to an implicitly declared buffer or 'channel' of the subtype 
+associated with the prefix of the 'Yield. Similarly, 'Consume may be
+use to read a value from that same channel;
+
+These attributes may only be used inside of a concurrent do statement, 
+and the scope of the implicit channel is the same as that of the do 
+statement.
+
+Since terminating a generator is a common idiom, we also allow an exit
+statement to be inserted in a do statement, which provides an alternate
+transfer of control mechanism out of the concurrent block, similar to
+how an exit statement may be used to exit a loop.
+
+Using these three features, we can now rewrite the above example as;
+
+   do
+      declare
+         X : Integer := 0;
+      begin
+         loop    -- endless loop
+            Integer'Yield(X);
+            X := X + 1;
+         end loop;
+      end;
+
+   and
+
+      for I in 1 .. 3 loop
+         Integer'Yield(1_000_000 + I);
+      end loop;
+
+   and
+
+      for I in 1 .. 5 loop
+         Put_Line ("Value=" & Integer'Image (Integer'Consume));
+      end loop;
+
+      Exit;
+
+   end do; 
+
+"Each exit_statement applies to a loop_statement {or concurrent do 
+statement}; this is the loop_statement {or do statement} being exited. 
+An exit_statement with a name is only allowed within the loop_statement 
+denoted by the name, and applies to that loop_statement. An 
+exit_statement without a name is only allowed within a loop_statement 
+{or do statement}, and applies to the innermost enclosing one. An 
+exit_statement that applies to a given loop_statement {or do statement} 
+shall not appear within a body or accept_statement, if this construct is 
+itself enclosed by the given loop_statement {or do statement}."
+
+Modify 5.7 (5)
+"For the execution of an exit_statement, the condition, if present, is 
+first evaluated. If the value of the condition is True, or if there is 
+no condition, a transfer of control is done to complete the 
+loop_statement {or do statement}. If the value of the condition is 
+False, no transfer of control takes place. "
+
+N.N.N Coroutine Attributes
+
+
+ The type-related operational attributes Consume and Yield read and write
+ values to an implicitly declared channel associated with a concurrent 
+ block statement. 
+ 
+Static Semantics
+
+For every subtype S of a specific type T, the following attributes are defined. 
+'Yield
+S'Yield denotes a procedure with the following specification: 
+
+ procedure S'Yield(Item : in T)
+
+S'Yield writes the value of Item to an implicitly declared channel 
+associated with a concurrent do statement.
+
+'Consume
+S'Consume denotes a function with the following specification: 
+
+function S'Consume return T;
+
+S'Consume reads the value of Item from an implicitly declared channel
+associated with a concurrent do statement. 
 
 !discussion
 
-** TBD.
+See Proposal.
 
 !ASIS
 
@@ -1702,5 +1846,69 @@
 could imagine having an unbounded-life generator/channel, using the equivalent
 of an allocator to initialize it and unchecked-deallocation to finalize it.  Not
 clear how important that capability would be.
+
+****************************************************************
+
+From: Brad Moore
+Sent: Wednesday, October 11, 2017  5:01 PM
+
+Here is the remainder of my homework.
+
+This is my first stab at this AI [this is version /01 of this AI - Editor.].
+It mostly builds upon the concurrent block statement defined in AI12-0119,
+
+but adds two new attributes;
+
+'Consume and 'Yield to read and write to an implicitly declared channel for
+the subtype of the prefix of the attribute.
+
+These may be used in a concurrent do statement to create coroutines, and pass
+values back and forth safely between different arms of the concurrent do.
+
+In addition I added an Exit statement that can be applied to a concurrent do
+statement, for convenience sake that makes it easier to exit the generator
+once all values needed have been generated and used.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, October 11, 2017  7:37 PM
+
+...
+> but adds two new attributes;
+> 
+> 'Consume and 'Yield to read and write to an implicitly declared 
+> channel for the subtype of the prefix of the attribute.
+
+I've been wondering what happens if the prefix of these attributes is of
+different types or even different (constrained) subtypes. For instance:
+
+    subtype S10 is String(1..10);
+    subtype S20 is String(1..20);
+    do
+       ...
+       S10'Yield (Obj10);
+       ...
+    and
+       ...
+       Obj20 := S20'Consume;
+    end do;
+
+Here, we've yielded a 10 character string and tried to consume a 20 character
+string.
+
+One can imagine various rules and/or checks to deal with this, but there
+doesn't seem to be any at all.
+
+----
+
+> In addition I added an Exit statement that can be applied to a 
+> concurrent do statement, for convenience sake that makes it easier to 
+> exit the generator once all values needed have been generated and used.
+
+I'm not a fan of this, as it begs a consistency problem with other kinds of
+statements (why can do be exited but not blocks or subprograms??). Moreover,
+I'd expect it to work more like Continue than Exit (it terminates its own
+branch but not the others).
 
 ****************************************************************

Questions? Ask the ACAA Technical Agent