-- -*- mode: eiffel -*-
-- $Id: except.se,v 1.2 2001/05/23 18:26:02 doug Exp $
-- http://www.bagley.org/~doug/shootout/
-- from: Friedrich Dominicus

-- <LOC-OFF>
indexing
    description: "Eiffel implementation of the Exceptions "
                 "in the shootout examples";
    note: "Tested with SmallEiffel and ISE-Eiffel"
-- <LOC-ON>

class
    EXCEPT

inherit 
    ARGUMENTS
creation

    make

feature -- Initialization

    high: INTEGER;
    low: INTEGER;

    high_exception: STRING is "high_exception";
    low_exception: STRING is "low_exception";

    run_n, outer_i: INTEGER;
    

    exc: EXCEPTIONS;
    
    make is
        do
            create exc;
            if argument_count /= 1 then
                io.put_string("exception_test <integer>%N");
                exc.die(1);
            end;
            if argument(1).is_integer then
                run_n := argument(1).to_integer;
            else
                io.put_string("Argument wasn't an integer, giving up%N");
                exc.die(1);
            end;
            outer_i := 1;
            some_fun(run_n);
        end;
    
    some_fun(n: INTEGER) is
        do
            from 
            invariant
                i_in_bounds: outer_i >= 1 and then outer_i <= n + 1;
            variant
                really_decreasing: n - outer_i + 1
            until outer_i > run_n
            loop
                high_fun(outer_i);
                -- an exception should be raised somwehere below
                -- `high_fun' in the call chain
                exc.raise("should not come here%N")
                -- outer_i := outer_i + 1
            end;
            io.put_string("Exceptions: HI=");
            io.put_integer(high);
            io.put_string(" / LO=");
            io.put_integer(low);
            io.put_character('%N');
        rescue
            outer_i := outer_i + 1;
            retry;
        end;
    
    
    high_fun (i: INTEGER) is
        do
            low_fun(i);
        rescue
            if exc.developer_exception_name.is_equal(high_exception)
then
                high := high + 1;
            end
        end;
    
    
    low_fun (i: INTEGER) is
        do
            -- exc.catch(exc.Developer_exception);
            blow_up(i);
        rescue
            if exc.developer_exception_name.is_equal(low_exception) then
                low := low + 1;
            end
        end;
    

    blow_up (i : INTEGER) is
        do
            if ((i \\ 2) = 0) then
                exc.raise(low_exception);
            else
                exc.raise(high_exception);
            end;
        end;

end -- class EXCEPT