May 2002

Exceptions

Introduction

Exception Semantics are Brief

Structured Programming and Error Handling

    Catching exceptions with classic structured programming is not pleasant. Below are three examples. The first will be an excerpt from some Java code, showing structured programming. The second being the same, but using Goto. The third using existing exception handling semantics.

    Structured Example

           FList record=PrimitiveFunction.getRecord();
           if (record!=null){
                Class classs=record.getClasss();
                if (classs!=null){
                     //DO REAL WORK
                }//endif
           }//endif
           //CONTINUE

    Structured programming, without exceptions, leads to an indent nightmare; the meaning of the code is lost. Once the indentation becomes overpowering, programmers resort to other methods to improve the look. One is to not indent; a little dangerous. Another is adding temporary state variables; and this will confuse code. The last is breaking the method into many helpers, scattering implementation.

    Goto Example

           FList record=PrimitiveFunction.getRecord();
           if (record==null) goto END;
           Class classs=record.getClasss();
           if (classs==null) goto END;
           //DO REAL WORK
           END:
           //CONTINUE

    The Goto example is better. It is very much like the Exception Handler, but does not hide the error identification code

    Exception Handler Example

           try{
                Class classs=PrimitiveFunction.getRecord().getClasss();
                //DO REAL WORK
           }catch (NullPointerException exception){
                //DO NOTHING
           }//catch
           //CONTINUE

    Exception semantics involve blocking a set of instructions and giving them a single exception handler. This is semantically efficient.

    If there is still doubt that exceptions are useful, we are reminded of the benefits we see so far: Exception handling reduces the size of the source code, with the added benefit of emphasizing the primary code path. These two benefits are sufficient to conclude that exception semantics are useful.

Exception Types

    Exceptions appear to be the result of differentiating between "normal" and "abnormal" operating conditions. The advantage of this distinction is to remove error handling from the code that handles normal operation. We will further partition our exceptions into types so to provide better semantics for each..

    We identify two aspects of exception handlers, the first is whether the exception handling is trivial, and the second is where they resume control. This makes for four different exception types: "Exit", "Abort", "Correction" and "Ignore". Each will be introduced in existing exception handling semantics, then we will discuss the best semantics for each.

    Exit
    The normal code has thrown an exception that makes the rest of the function irrelevant. We would like to do some cleanup and exit the function gracefully.

      try{
           //DO WORK
      }catch (Exception exception){
           //DO SOME CLEANUP
           return;
      }//catch
      //CONTINUE

    Abort (aka Runtime Exception)
    The Abort exception type is a simple version of the Exit exception type. We, cancel all execution of the current frame and return an exception to the caller.

      try{
           //DO WORK
      }catch (Exception exception){
           return exception;
      }//catch
      //CONTINUE

    Correction
    If an exception is to be handled, and corrected, we will have to explicitly mention how we are going to do the correction. This means detailing both paths: one for normal operation, and the other for exception handling.

      try{
           //DO NORMAL OPERATION
      }catch (Exception exception){
           //DO CORRECTION
      }//catch
      //CONTINUE

    Ignore
    Like Correction, but there is nothing to correct. It is useful for prototyping and for those few legitimate cases where only side effects are important.

      try{
           //DO WORK
      }catch (Exception exception){
           //DO NOTHING
      }//catch
      //CONTINUE

Further Brevity

    We now look at the particular semantic optimizations that can be made for each of the exception types. We start with the simplest handlers first

    The Abort exception type is the most common, and all instances are handled in the same way. We can completely remove any mention of exceptional program flow from the code and leave the exception handling implicit (default). We show an entire function below to stress the complete lack of exception handling code.

      METHOD MyFunction() RETURNS Object{
           //DO WORK
      }//MyFunction

    The Ignore exception type is also trivial; mentioning how to handle the exception is identical to Abort (do nothing). We only have to indicate where to continue in the event of an exception. In this first case, we can ignore any exceptions that appear in a single line of code

      CATCH (e AS Exception) IGNORE;

      //TRY A LINE OF CODE
      //CONTINUE
      //TRY ANOTHER LINE OF CODE
      //CONTINUE

    In the second case we may have a block of code that must be run as a transaction, execution must resume right after that, exception or not.

      CATCH (e AS Exception) TRY
           //DO OPERATIONS AS TRANSACTION
      END Exception
      //CONTINUE

    The Exit exception type only has to indicate the actions needed to cleanup before exiting. Therefore the exit code can be completely separated from the normal operations.

      CATCH (e AS Exception) DO
           //DO SOME CLEANUP
           RETURN;   //AND EXIT 
      END Exception

      //DO NORMAL OPERATION

    The CATCH/DO statements are not executed in lexical order, but rather executed in the event of an exception in any code following. The CATCH/DO stament has implicit lexical scope identical to variable declarations. We may want to handle the same exception in different ways in different points in the code. In this case blocking is unavoidable, but indenting is not:

      CATCH (e AS Exception) DO
          //DO SOME CLEANUP AND EXIT
      TRY
          //DO NORMAL OPERATION
      END Exception

      CATCH (e AS Exception) DO
          //DO SOME OTHER CLEANUP AND EXIT
      END Exception
      //CONTINUE

    The Correction exception type has too many links with the original code to be far removed from it. We must default back to existing exception handling semantics. We could reverse the order of the normal code from the exceptional code (below), but from a logical point of view it does not matter.

      CATCH (e AS Exception) DO
           //DO CORRECTION
      TRY
           //DO NORMAL OPERATION
      END Exception
      //CONTINUE

    The order of TRY and DO does not matter, therefore the following is also valid.

      CATCH (e AS Exception) TRY
           //DO NORMAL OPERATION
      DO
           //DO CORRECTION
      END Exception
      //CONTINUE

Summary

    Exception handling semantics have been minimized by identifying exception types and optimizing semantics for each.

Update


may 2002, improved clarity

feb 2000, first writing