// MC# Examples
// Parallel prime number generatation by Eratosthenes (sieve) method.
// Usage : CSieve.exe  < N >

class Eratosthenes   {
 public static void Main(String[] args) {
  if ( args.Length < 1 )
  {
     Console.WriteLine( "Usage: CSieve.exe number" );
     return;
  }
  int N = System.Convert.ToInt32 (args[0] );
  Eratosthenes E = new  Eratosthenes();
  new CSieve().Sieve ( E.getNat, E.sendPrime );
  for ( int n=2; n <= N; n++ )
    E.Nats ! ( n );
  E.Nats ! ( -1 );
  int p=0;
  while  (  (  p=(int) E.getPrime?() ) != -1 )
   Console.WriteLine ( p );
 }

 public handler getNat  int()  & channel Nats ( int n ) {
    return ( n );
 }

 public handler getPrime int()& channel sendPrime( int p ) {
   return ( p );
 }
}

class  CSieve  {
 public async Sieve ( handler int() getList, channel (int) sendPrime )
 {
  int  p = (int)getList?();
  sendPrime ! ( p );
  if  ( p != -1 )
  {
   new CSieve().Sieve ( hin, sendPrime );
   filter ( p, getList, cout );
  }
 }

 public handler hin int()  &  channel cout ( int x ) {
  return  ( x );
 }

 void filter (int p, handler int() getList,
                     channel (int) cfiltered ){
  int n=0;
  while ( (  n= (int)getList?() ) != -1 )
    if ( n % p != 0 ) cfiltered ! ( n );
  cfiltered ! ( -1 );
 }
}