(* -*- mode: sml -*-
 * $Id: except.smlnj,v 1.2 2001/07/09 00:25:27 doug Exp $
 * http://www.bagley.org/~doug/shootout/
 * Translated from except.ocaml by Stephen Weeks
 *)

structure Test : sig
    val main : (string * string list) -> OS.Process.status
end = struct

fun incr r = r := !r + 1
fun print_endline s = (print s; print "\n")
fun for (start, stop, f) =
   let
      fun loop i =
     if i > stop
        then ()
     else (f i; loop (i + 1))
   in
      loop start
   end
   
exception HiException of int
exception LoException of int

val hi = ref 0
val lo = ref 0

fun blowup n =
  if n mod 2 = 0 then raise (LoException n)
  else raise (HiException n)

fun lo_fun n =
  blowup n
  handle LoException ex => incr lo

fun hi_fun n =
  lo_fun n
  handle HiException ex => incr hi

fun some_fun n =
  hi_fun n
  handle x =>
     (print_endline "Should not get here.";
      raise x)

fun atoi s = case Int.fromString s of SOME num => num | NONE => 0;
fun printl [] = print "\n" | printl(h::t) = ( print h ; printl t );
   
fun main (name, args) =
   let
      val n = atoi (hd (args @ ["1"]))
      val _ = for (1, n, some_fun)
   in
      printl ["Exceptions: HI=",
          Int.toString (!hi),
          " / LO=",
          Int.toString (!lo)];
      OS.Process.success
   end
end

val _ = SMLofNJ.exportFn("except", Test.main);