----------------------------------------------------------------------
-- Primzahlen durch Siebmethode:
-- erzeuge Folge von Folgen [[2,3,4,5,...],[3,5,7,9],...]
-- durch Elimination aller Fielfachen des 1. Elements der Vorgaengerfolge;
-- die jeweils ersten Elemente bilden Folge der Primzahlen
----------------------------------------------------------------------

with Stringpack; use Stringpack;
procedure Primes is

   ----------------------------------------------- Typ der Zahlenfolge
   type Seq;  -- incomplete type declaration to allow recursive construction
   type A_Seq is access Seq;

   task type Seq(Pred: A_Seq) is     -- discriminant names predecessor sequence
      entry Head(Item: out Integer); -- gives first element
      entry Next(Item: out Integer); -- gives all elements on iterated calls
   end Seq;

task body Seq is
   First, Elem, Prime: Integer;
begin
   if Pred = null then  -- base case: seq= 2,3,4,5,...
      First := 2; Elem := 2;
      loop
         select
            accept Head(Item: out Integer) do
               Item := First;
            end Head;
         or
            accept Next(Item: out Integer) do
               Item := Elem;
            end Next;

            Elem := Elem +1;
         or
            terminate;
         end select;
      end loop;

   else  -- general case: seq = crossout multiples in predecessor seq
      Pred.Head(Prime); Pred.Next(Elem);
      while (Elem mod Prime = 0) loop
         Pred.Next(Elem);
      end loop;
      First := Elem;

      loop
         select
            accept Head(Item: out Integer) do
               Item := First;
            end Head;
         or
            accept Next(Item: out Integer) do
               Item := Elem;
            end Next;

            Pred.Next(Elem);
            while (Elem mod Prime = 0) loop
               Pred.Next(Elem);
            end loop;
         or
            terminate;
         end select;
      end loop;
   end if;
end Seq;  ------------------------------------------------------------

----------------------------------------------- Folge von Zahlenfolgen
task Seq_Of_Seqs is
   entry Next(Item: out A_Seq);  -- gives all elements on iterated calls
end Seq_Of_Seqs;

task body Seq_Of_Seqs is
   Previous, Elem: A_Seq;  -- previous = null on initialization!
begin
   loop
      Elem := new Seq(Previous); -- create next seq (with a link to previous sequence)
      select
         accept Next(Item: out A_Seq) do
            Item := Elem;
         end Next;
      or
         terminate;
      end select;

      Previous := Elem;
   end loop;
end Seq_Of_Seqs; -----------------------------------------------------

Res, From, To: Integer;
Current_Seq: A_Seq;
begin
   Print("give from and to");
   From := Getint;
   To := Getint;
   for I in 1..From-1 loop  -- skip
      Seq_Of_Seqs.Next(Current_Seq);
   end loop;

   for I in From..To loop
      Seq_Of_Seqs.Next(Current_Seq);
      Current_Seq.Head(Res);
      Print(">" & Res);
   end loop;
end Primes;
