MODULE sieve ;

CONST
    startPrime = 2;
    max        = 51;

TYPE
    ArrayType = ARRAY [ 2 .. 51 ] OF INTEGER ;

VAR
    newSieve : ArrayType ;

PROCEDURE init (VAR newSieve : ArrayType) ;
VAR
    index : INTEGER ;

BEGIN
    index := startPrime ;
    LOOP
        IF index > max THEN EXIT END ;
        newSieve [index] := 1 ;
        index := index + 1 ;
    END ;
END init ;
(* END PROCEDURE END PROCEDURE END PROCEDURE *)

PROCEDURE calculateLimit (VAR limit : INTEGER ; VAR newSieve : ArrayType ) ;

BEGIN
    limit := 1 ;
    LOOP
        IF limit * limit > 51 THEN EXIT END ;
        limit := limit + 1 ;
    END ;
    limit := limit - 1 ;
END calculateLimit ;
(* END PROCEDURE END PROCEDURE END PROCEDURE *)

PROCEDURE siftPrimes (limit, max : INTEGER ; VAR newSieve : ArrayType ) ;

VAR
    currPrime, mult : INTEGER ;

BEGIN
    currPrime := startPrime ;

    LOOP
        IF currPrime > limit THEN EXIT END ;
        mult := 2 ;
        LOOP
            IF mult * currPrime > 51 THEN EXIT END ;
            newSieve[mult * currPrime] := 0 ;
            mult := mult + 1 ;
        END ;
        LOOP
            currPrime := currPrime + 1 ;
            IF newSieve [ currPrime ] <> 0 THEN EXIT END ;
        END ;
    END ;
END siftPrimes ;
(* END PROCEDURE END PROCEDURE END PROCEDURE *)

PROCEDURE printPrimes (max : INTEGER ; VAR newSieve : ArrayType );
VAR
    index : INTEGER ;

BEGIN
    index := startPrime ;
    LOOP
        IF index > max THEN EXIT END ;
        IF newSieve [ index ] = 1 THEN
            IO.WrInt ( index , 7 ) ;
            IO.WrLn ;
        END ;
        index := index + 1 ;
    END ;
END printPrimes ;
(* END PROCEDURE END PROCEDURE END PROCEDURE *)


VAR
    limit : INTEGER ;

BEGIN (* The main program starts here *)

    init (newSieve) ;
    calculateLimit (limit, newSieve) ;
    siftPrimes (limit, max, newSieve) ;
    printPrimes (max, newSieve) ;

END sieve .