/* Exception.h      -*-objc-*-
 *
 * Copyright Niels Möller <nisse@lysator.liu.se> 1995
 *
 * Freely distributable under the terms and conditions of the
 * GNU General Public License.
 */

/* Exceptions are organized in a tree like hierarchy, where a protocol
 * represents a type of error. This decouples the hierarchy of error
 * types from the inheritance hierarchy of implementations. As an extra
 * bonus, some kind of multiple inheritance is possible.
 *
 * The most important branch of this hierarchy is the type AnyError and
 * its decendants. Errors abort the program if they are raised but nit
 * catched.
 *
 * In contrast, there may be other kinds of exceptions, of type
 * AnyException but not AnyError, which are simply ignored if they are
 * raised and not catched.
 *
 * This file defines the classes that implement raising of exceptions,
 * and also defines an first draft of a exception hierarchy.
 *
 * One might integrate catch and throw into this hierarchy too,
 * but I don't think that is a good idea. */

/* Name conventions: Error types (that is, protocols) end in "Error".
 * A class implementing a particular error has a descriptive name, for
 * example "OutOfMemory" or "ThrowWithoutCath". */

#ifndef OBJC_EXCEPTION_H_INCLUDED
#define OBJC_EXCEPTION_H_INCLUDED

#include <objc/Object.h>
#include <StackFrame.h>

/* Perhaps this should be a plain id instead? */
typedef Protocol * exception_type; 

/* Protocols for the error hierarchy */

@protocol AnyException
- (void) raise;           /* Usually does not return */
- (const char *) message; /* Human readably description */
- (void) finished;        /* Should be sent by a handler when finished */
- (BOOL) ofExceptionType: (exception_type) type;
@end /* AnyException */

@protocol AnyError <AnyException>
@end /* AnyError */

@protocol StorageError <AnyError>
@end /* StorageError */

@protocol MemoryError <StorageError>
@end /* MemoryError */

@protocol ThrowError <AnyError>
- value;
- tag;
@end /* ThrowError */


/* Classes for some exceptions */

@interface Exception : Object <AnyException>
{
}
- (void) noHandler;
@end /* Exception */

@interface Error: Exception <AnyError>
@end /* Error */

@interface SimpleError : Error
{
  const char *message;
  BOOL constantMessage;
  BOOL constantObject;
}
- message: (const char *) msg;
- constantMessage: (BOOL) flag; /* FALSE means don't free the message string */
- constant: (BOOL) flag;        /* TRUE means ignore the -finished message */
@end /* SimpleError */

/* This kind of error is usually allocated at startup, and never freed.
 * This is so that no memory allocation is needed to signal that the
 * program has run out of memory. */
@interface OutOfMemory : SimpleError <StorageError>
+ newMessage: (const char *) msg;
@end /* OutOfMemory */

@interface ThrowWithoutCatch : Error <ThrowError>
{
  id value;
  id tag;
}
- tag: newTag;
- value: newValue;
@end

#endif OBJC_EXCEPTION_H_INCLUDED
