This first behavior could be called no error handling, and the trouble with it is that it does not give any opportunity to recover from some minor errors. As a result, in early Pliant release, there was a kind of error handling in the compiler so that we can recover from failed to compile expression, but it was not a general mechanism.
The second behavior could be called the optimistic one: it assumes that poping the stack and cleanly destroying local variables on it will enable to safely 'jump' to the error handler.If you pop the stack and do nothing else, the most visible result is a memory leak because complex local variables (strings, arrays) will not be freed, so in object oriented languages, since we have a destruction function for each data type, compiler designers said: we are going to generate a special task with a list of all objects have a destruction routine, so when poping up the stack to get back to the error handler, we'll do the garbage.That's dealing with the most visible part of the trouble, but not with the hardest one, which is that poping the stack up to the error handler means exiting from all the functions in the middle, so what about:
var Sem s
Now the Pliant behavior: when the error occurs, we record it ... and continue, so each function in the middle between the current point and the error handler will continue to execute ... until either it reaches the normal end or gets to a point where the programmer said: if we have a recorded error, you can safely return from this point.The draw back of it is that jumping from the error point to the error handler will take time, but since an error is an exceptional event, who cares ?On the other hand, we'll have less buggy programs.
In Pliant, some of the errors will be notified as fatal, which mean that we get back to no error handling for these ones. The most important one of these being "out of memory". I decided not to allow to recover from "out of memory" for the following reasons:
As a summary for this introduction on Pliant error handling, i'd say that, in fact, various Pliant programs can use all the three mechanisms described at the beginning, none being perfect.
while (condition ?)
function foo ...
Now, you still can create your own high level error handling functions using the low level mechanism described below, which has much more capabilities than the few high level functions that i have already written, and use meta programming in order to create nice new controls and apply changes to the program on the fly.
field Str action
field Pointer:ActionRecord next
function action_push_record r msg
arg_w ActionRecord r ; arg Str msg
function action_pull_record r
arg_rw ActionRecord r
function action_top_record -> r
arg_RW ActionRecord r
field Int id
field Arrow context
field Str message
field Int filter
field Pointer:ErrorRecord next
function error_push_record r filter
arg_w ErrorRecord r ; arg ErrorID filter
function error_pull_record r
arg_rw ErrorRecord r
function error_top_record -> r
arg_RW ErrorRecord r
function error_notify_fatal id msg
arg ErrorID id ; arg Str msg
function error_notify id context msg
arg ErrorID id ; arg Address context ; arg Str msg
function error_notified -> e
arg CBool e
function error_propagate src dest
arg ErrorRecord src dest
function error_allocate_id -> id
arg ErrorID id