Exception Handling
- Posted by Chris Bensler <bensler at mail.com> Mar 24, 2002
- 439 views
I'm hoping to get some feedback on this library. Positive and negative criticism is appreciated. I've written an error library and implemented what I 'think' is a exception handling system. Sorry for the lack of documentation, but it's still in prototype. Basically, I know nothing of exception handling other than my own theories and the other implementations that I have seen. I'd like to get some more insight as to the how and why. Is this system sufficient? What are the main properties of an exception handling system? My concept is to create exception handlers. The handlers take an object parameter to be tested, check it, and make any changes to try and keep the data within the exception definition. If the data is fit, the handler passes it back. Otherwise, an exception should be thrown from the handler so that an error is trigered. There is no error stack. If an exception is thrown, an error occurs. You can't catch errors, they are caught by the handlers. In oder to 'catch' an error, you would have to implement the catch through the handler. The example only demonstrates how the system works. It doesn't really demonstrate the flexibility that it can provide. error.e is below the example <EXAMPLE> include error.e -- display msg and wait for a keypress global procedure wait(sequence msg) if length(msg) then puts(1,msg) end if while get_key()=-1 do end while end procedure -- if place = 0 round to nearest integer -- if place > 0 then round to decimal place ( 1=0.1, 2=0.01 ) -- if place < 0 then round to tens place ( -1=10, -2=100 ) global function round(atom a, integer place) atom b b = floor(a) return b + ((a-b) >= (0.5*power(10,-place))) end function -- exception handler -- if data > 10, then error function over_10_handler(atom data) if data > 10 then throw_exception() end if return round(data,0) end function constant err_over_10 = new_exception(routine_id("over_10_handler"),"%d is greater than 10") wait(sprintf("%g press any key\n",exception(0, err_over_10))) wait(sprintf("%g press any key\n",exception(3.7, err_over_10))) wait(sprintf("%g press any key\n",exception(9.8, err_over_10))) wait(sprintf("%g press any key\n",exception(13, err_over_10))) <END EXAMPLE> <ERROR.E> include machine.e -- GENERAL ERROR ROUTINES -- global procedure fatal_error(sequence msg) crash_message(msg) ? 1/0 end procedure integer error_rID error_rID=routine_id("fatal_error") global procedure error(sequence msg) call_proc(error_rID,{msg}) end procedure global procedure on_error(integer expr, sequence msg) if expr then error(msg) end if end procedure global procedure set_error_handler(integer err_rID) if err_rID <=0 then error_rID = routine_id("fatal_error") end if error_rID = err_rID end procedure -- EXCEPTION HANDLING ROUTINES -- -- {{exception_rIDs},{error_messages},{exception_data}} constant ERR_rID=1, ERR_MSG=2 sequence stack stack={{},{}} -- this will be set to 1 if an exception handler is currently being processed -- throw_exception() can only be called from an exception handler integer err_check err_check=0 global function new_exception(integer err_rID, sequence msg ) integer f f = find(err_rID,stack[ERR_rID]) if f then return f else stack[ERR_rID] &=err_rID stack[ERR_MSG] &={ msg } return length(stack[ERR_rID]) end if end function global function exception(object err_data, integer err_id) if stack[ERR_rID][err_id] < 0 then -- there is no exception handler routine -- crash and dump ex.err. error("Exception!: "&sprintf(stack[ERR_MSG][err_id],{err_data})) else err_check = 1 err_data = call_func(stack[ERR_rID][err_id],{err_data}) if not err_check then -- crash and dump ex.err. error("Exception! : "&sprintf(stack[ERR_MSG][err_id],{err_data})) end if end if err_check = 0 return err_data end function global procedure throw_exception() if not err_check then error("tried to throw and exception() outside of an exception handler") end if err_check=0 end procedure <END ERROR.E> What do you think? Chris