1. Exception Handling
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