May 2002
Returns
Introduction
Before a successful model of exceptions and function returns can be completed it was necessary for me to inspect exactly what these 'objects' were.
Identifying what exceptions are will be shown to reduce the sphere of consideration to just modeling returns. More information can be found in the Functions document.
Error Handling without Exceptions
We start our exploration by inspecting how structured pseudocode, without the ability to throw exceptions, is used to handle errors. Our example will be the division instruction. We assume that the numerator and denominator parameters are both non-negative values.
Given a function, the most naive method of handling errors is to not give the function any input that will cause an error. Note that we identify two things: what type of error can occur, and how to handle it.
EG1
if (denominator==0){
//DIVIDE BY ZERO ERROR
}else{
return divideFirstBySecond(numerator, denominator);
}//endif
Checking for bad parameter values every time this function is used wastes line space, and amplifies human error. It would be better to group the error checking with the called function. This can be done a couple of ways. The second example will handle the error before returning. The third example will take advantage of unused return codomain values to signal the caller to the type of error.
EG2
public double divideInstrution(double numerator, double denominator){
if (denominator==0){
return +INF;
}else{
return divideFirstBySecond(numerator, denominator);
}//endif
}//divideInstruction
EG3
public double divideInstrution(double numerator, double denominator){
if (denominator==0){
return -1; //Remember, numerator and denominator >=0
}else{
return divideFirstBySecond(numerator, denominator);
}//endif
}//divideInstruction
The latter example is most interesting. It delegates the ultimate solution to the problem to another portion of code. The two aspects of error handling, what and how, have been split and handled separately. Furthermore, I must emphasize the use of unused codomain values. If the function uses the entire codomain, then the developer is limited to handling errors similar to the first two examples.
What is an Exception?
Our last example shows that by returning an error code we can delegate how the exceptional condition is handled. So in general, exceptions are simply extensions to the function codomain, and are objects just like any other return value.
Extending a function's codomain can be done easily when the codomain is an object reference: extend by allowing references to exceptions. When the return is a primitive value, like int or float, the solutions are more complex and maybe impossible. The DBOS does not have primitives, all returns are references to objects.
If exceptions are return values, then what does it mean to return a value?
Returns as Messages
We simplify our exposition, and assume that only one return value is allowed for each function call. This is an inconsequential restriction: It can be worked around by declaring a special return type to hold multiple values.
Modeling returns is more difficult for the DBC than in standard languages. Most languages put the return on a stack, and is handled implicitly. I have mentioned the desire not to have a stack in the Functions document, so an implicit solution is not available. Second I want everything to be an object, that includes the concept of 'return'.
Reviewing stack based systems: the return value is placed on the stack. The caller immediately takes this value off and places it in a local frame variable for further use. The stack is acting like a container for the transport of return values.
Actually, modeling returns is just realizing that we want to use the 'container' concept. The embodiment of a container could easily be a message. Since we have assumed that each return consists of only one value, the value returned and the return message are the same object. In other words, the return value is just a message from callee to caller.
The MSM requires that all incoming messages are delivered to the context variable.
Summary
We have explained exception handling in terms of return values. By simply increasing the codomain of a function, we are able to model exceptions as return values. Return values are transported, via messages, from the callee back to the caller. In the MSM specifically, return values appear in the context variable upon the completion of the callee.
May 2002 - edit for more readability
Jul 2001 - Completed draft
Feb 2000 - first writing