(* The Great Win32 Language Shootout http://dada.perl.it/shootout/

   contributed by Isaac Gouy (Modula2 novice)

   To build: xc =m except
   To run:   except 200000
*)

MODULE Except;
<* procinline + *>

(* Prefer unqualified procedures *)
FROM LanguageShootout IMPORT N;

IMPORT EXCEPTIONS;
FROM STextIO IMPORT WriteString, WriteLn;
FROM SWholeIO IMPORT WriteCard;


VAR lo, hi: CARDINAL;
    n, i: CARDINAL;
    source: EXCEPTIONS.ExceptionSource;

TYPE Exceptions = (Lo_Exception, Hi_Exception);


PROCEDURE Exception(): Exceptions;
BEGIN
   RETURN VAL(Exceptions, EXCEPTIONS.CurrentNumber(source));
END Exception;


PROCEDURE BlowUp(i: CARDINAL);
BEGIN
   IF ODD(i) THEN
      EXCEPTIONS.RAISE(source, ORD(Hi_Exception), "HI Exception");
   ELSE
      EXCEPTIONS.RAISE(source, ORD(Lo_Exception), "LO Exception");
   END;
END BlowUp;


PROCEDURE Lo_Function(i: CARDINAL);
BEGIN
   BlowUp(i);
EXCEPT
   IF Exception() = Lo_Exception THEN
      INC(lo);
      RETURN;
   END;
END Lo_Function;


PROCEDURE Hi_Function(i: CARDINAL);
BEGIN
   Lo_Function(i);
EXCEPT
   IF Exception() = Hi_Exception THEN
      INC(hi);
      RETURN;	
   END;
END Hi_Function;


PROCEDURE Some_Function(i: CARDINAL);
BEGIN
   Hi_Function(i);
EXCEPT
   WriteString("We shouldn't get here!");
   WriteLn;
   RETURN;
END Some_Function;


BEGIN
   n := N();
   lo := 0;
   hi := 0;
   EXCEPTIONS.AllocateSource(source);

   WHILE n > 0 DO
      DEC(n);
      Some_Function(i);
   END;  	

   WriteString("Exceptions: HI="); WriteCard(hi,1);
   WriteString(" / LO="); WriteCard(lo,1); WriteLn;
END Except.