Exceptions

Sather 1.0 has fully implemented exception handling. An exception may be raised by calling the raised statement

    foo is
        raise("foo not implemented. This is a test");

Within the raise statement may be any arbitrary expression which returns some object. The type of the object determines the class of the exception. Exceptions may be caught by simply protecting for the appropriate type. In the protect clause, the exception may be referred to by the built in variable "exception" In fact, you can look at the tail half of the protect as a typecase on the exception object.

        protect
            foo;
        when STR then #OUT+exception+"\n" end;
Exceptions are passed to higher contexts until a handler is found and the exception is caught. The compiler provides a default handler for string exceptions, which is why most of the exceptions raised are string exceptions.

As a more complex example, here's an exception that could be used in the STR_CURSOR class

 
        class STR_CURSOR_EX < $STR is
	  -- Hold information that may be used when the exception is raised
          readonly attr s: STR_CURSOR;
          readonly attr error_type: STR;

          create(s: STR_CURSOR,m: STR): SAME is
             res ::= new;
             res.s := s;
             res.error_type := m;
             return(res);
         end;

         str: STR is
           res: STR := "Error type:\n"+error_type+"\n";
           res := res + "String cursor location:"+s.current_loc+"\n";
           return(res);
         end;
       end;
In the STR_CURSOR class we may then raise the exception as follows  
        advance_one_char is
          if (current_loc = buf.size -1) then -- some error condition
             raise #STR_CURSOR_EX(self,"Attempt to read past the end of buf");
          end;
        end;
We may then catch this exception by:  
        protect
           my_string_cursor.advance_one_char;
        when STR_CURSOR_EX then  #OUT+exception.str+"\n"; end;

Note that the exception object in this case has a whole bunch of other information that we might make use of - the exact location in the string cursor, for instance. This information may be used to report the error in a manner that is suitable to the client.

 

Pros and Cons of Using Exceptions

Exceptions are very convenient, but create a significant overhead and should be used only for error states. Programming with them is tempting, but should be avoided. For instance, in the STR_CURSOR class, we can make use of exceptions for parsing. Testing whether a bool exists can be done as follows

        test_bool: BOOL is
           protect 
               current_state ::= save_state;
               b ::= get_bool;
               restore_state(current_state);
          when STR_CURSOR_EX then return(false); end;
          return(true);
        end;
However, this is a much higher overhead way of accomplishing the basic test.

Alternatives to Exceptions

The alternative to using exceptions is to use a sticky error flag in the class, as is done by IEEE exceptions and the current FILE classes. This has problems such as the fact that the outermost error is logged, not the most immediate one, and it is very easy to forget to catch the exception. However, it is of low overhead and would be suitable for use in the previous test_bool case.



Benedict A. Gomes
Mon Apr 29 10:12:43 PDT 1996