123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289 |
- @node Condition system
- @section Condition system
- @stindex exceptions
- @stindex conditions
- As of version 1.3 (different from all older versions), Scheme48
- supports two different condition systems. One of them, the original
- one, is a simple system where conditions are represented as tagged
- lists. This section documents the original one. The new condition
- system is [SRFI 34, 35], and there is a complicated translation layer
- between the old one, employed by the run-time system, and the new one,
- which is implemented in a layer high above that as a library, but a
- library which is always loaded in the usual development environment.
- See the [SRFI 34, 35] documents for documentation of the new condition
- system. [SRFI 34] is available from the @code{exceptions} structure;
- SRFI 35, from the @code{conditions} structure.
- @strong{Note:} The condition system changed in Scheme48 version 1.3.
- While the old one is still available, the names of the structures that
- implement it changed. @code{Signals} is now @code{simple-signals},
- and @code{conditions} is now @code{simple-conditions}. The structure
- that @code{signals} @emph{now} names implements the same interface,
- but with [SRFI 34, 35] underlying it. The structure that the name
- @code{conditions} @emph{now} identifies [SRFI 35]. You will have to
- update all old code that relied on the old @code{signals} and
- @code{conditions} structure either by using those structures' new
- names or by invasively modifying all code to use [SRFI 34, 35]. Also,
- the only way to completely elide the use of the SRFIs is to evaluate
- this in an environment with the @code{exceptions-internal} and
- @code{vm-exceptions} structure open:
- @lisp
- (begin (initialize-vm-exceptions! really-signal-condition)
- ;; INITIALIZE-VM-EXCEPTIONS! returns a very large object,
- ;; which we probably don't want printed at the REPL.
- #t)@end lisp
- @subsection Signalling, handling, and representing conditions
- @cindex conditions
- @cindex exceptions
- @cindex errors
- @cindex warnings
- @cindex signalling conditions
- @cindex condition types
- @cindex condition handlers
- Scheme48 provides a simple condition system.@footnote{Note, however,
- that Scheme48's condition system is likely to be superseded in the near
- future by [SRFI 34, SRFI 35].} @dfn{Conditions} are objects that
- describe exceptional situations. Scheme48 keeps a registry of
- @dfn{condition types}, which just have references to their supertypes.
- Conditions are simple objects that contain only two fields, the type
- and the type-specific data (the @dfn{stuff}). Accessor procedures
- should be defined for particular condition types to extract the data
- contained within the `stuff' fields of instances of of those condition
- types. Condition types are represented as symbols. @dfn{Condition
- handlers} are part of the system's dynamic context; they are used to
- handle exceptional situations when conditions are signalled that
- describe such exceptional situations. @dfn{Signalling} a condition
- signals that an exceptional situation occurred and invokes the current
- condition handler on the condition.
- Scheme48's condition system is split up into three structures:
- @table @code
- @item simple-signals
- Exports procedures to signal conditions and construct conditions, as
- well as some utilities for common kinds of conditions.
- @item handle
- Exports facilities for handling signalled conditions.
- @item simple-conditions
- The system of representing conditions as objects.
- @end table
- @stindex simple-signals
- The @code{simple-signals} structure exports these procedures:
- @deffn procedure make-condition type-name stuff @returns{} condition
- The condition object constructor.
- @end deffn
- @deffn procedure signal-condition condition @returns{} values (may not return)
- @deffnx procedure signal type-name stuff @dots{} @returns{} values (may not return)
- @code{Signal-condition} signals the given condition. @code{Signal} is
- a convenience atop the common conjunction of @code{signal-condition}
- and @code{make-condition}: it constructs a condition with the given
- type name and stuff, whereafter it signals that condition with
- @code{signal-condition}.
- @end deffn
- @deffn procedure error message irritant @dots{} @returns{} values (may not return)
- @deffnx procedure warn message irritant @dots{} @returns{} values (may not return)
- @deffnx procedure syntax-error message irritant @dots{} @returns{} expression (may not return)
- @deffnx procedure call-error message irritant @dots{} @returns{} values (may not return)
- @deffnx procedure note message irritant @dots{} @returns{} values (may not return)
- Conveniences for signalling standard condition types. These procedures
- generally either do not return or return an unspecified value, unless
- specified to by a user of the debugger. @code{Syntax-error} returns
- the expression @code{(quote syntax-error)}, if the condition handler
- returns to @code{syntax-error} in the first place.
- @cindex error messages
- @cindex condition messages
- By convention, the message should be lowercased (@ie{} the first word
- should not be capitalized), and it should not end with punctuation.
- The message is typically not a complete sentence. For example, these
- all follow Scheme48's convention:
- @itemize @w{}
- @item argument type error
- @item wrong number of arguments
- @item invalid syntax
- @item ill-typed right-hand side
- @item out of memory, unable to continue
- @end itemize
- These, on the other hand, do not follow the convention and should be
- avoided:
- @itemize @w{}
- @item Argument type error:
- @item An argument of the wrong type was passed.
- @item possible type mismatch:
- @item Luser is an idiot!
- @end itemize
- Elaboration on a message is performed usually by wrapping an irritant
- in a descriptive list. For example, one might write:
- @lisp
- (error "invalid argument"
- '(not a pair)
- `(while calling ,frobbotz)
- `(received ,object))@end lisp
- @noindent
- This might be printed as:
- @example
- Error: invalid argument
- (not a pair)
- (while calling #@{Procedure 123 (frobbotz in ...)@})
- (received #(a b c d))@end example
- @end deffn
- @cindex installing condition handlers
- @stindex handle
- The @code{handle} structure exports the following procedures:
- @deffn procedure with-handler handler thunk @returns{} values
- Sets up @var{handler} as the condition handler for the dynamic extent
- of @var{thunk}. @var{Handler} should be a procedure of two arguments:
- the condition that was signalled and a procedure of zero arguments that
- propagates the condition up to the next dynamically enclosing handler.
- When a condition is signalled, @var{handler} is tail-called from the
- point that the condition was signalled at. Note that, because
- @var{handler} is tail-called at that point, it will @emph{return} to
- that point also.
- @strong{Warning:} @code{With-handler} is potentially very dangerous.
- If an exception occurs and a condition is raised in the handler, the
- handler itself will be called with that new condition! Furthermore,
- the handler may accidentally return to an unexpecting signaller, which
- can cause very confusing errors. Be careful with @code{with-handler};
- to be perfectly safe, it might be a good idea to throw back out to
- where the handler was initially installed before doing anything:
- @lisp
- ((call-with-current-continuation
- (lambda (k)
- (lambda ()
- (with-handler (lambda (c propagate)
- (k (lambda () @var{handler body})))
- (lambda () @var{body}))))))@end lisp
- @end deffn
- @deffn procedure ignore-errors thunk @returns{} values or condition
- @deffnx procedure report-errors-as-warnings thunk message irritant @dots{} @returns{} values
- @code{Ignore-errors} sets up a condition handler that will return error
- conditions to the point where @code{ignore-errors} was called, and
- propagate all other conditions. If no condition is signalled during
- the dynamic extent of @var{thunk}, @code{ignore-errors} simply returns
- whatever @var{thunk} returned. @code{Report-errors-as-warnings}
- downgrades errors to warnings while executing @var{thunk}. If an error
- occurs, a warning is signalled with the given message, and a list of
- irritants constructed by adding the error condition to the end of the
- list @var{irritant} @dots{}.
- @end deffn
- @cindex conditions
- @cindex condition types
- @stindex simple-conditions
- Finally, the @code{simple-conditions} structure defines the condition
- type system. (Note that conditions themselves are constructed only by
- @code{make-condition} (and @code{signal}) from the
- @code{simple-signals} structure.) Conditions are very basic values
- that have only two universally defined fields: the type and the stuff.
- The type is a symbol denoting a condition type. The type is specified
- in the first argument to @code{make-condition} or @code{signal}. The
- stuff field contains whatever a particular condition type stores in
- conditions of that type. The stuff field is always a list; it is
- created from the arguments after the first to @code{make-condition} or
- @code{signal}. Condition types are denoted by symbols, kept in a
- global registry that maps condition type names to their supertype
- names.
- @deffn procedure define-condition-type name supertype-names @returns{} unspecified
- Registers the symbol @var{name} as a condition type. Its supertypes
- are named in the list @var{supertype-names}.
- @end deffn
- @deffn procedure condition-predicate ctype-name @returns{} predicate
- Returns a procedure of one argument that returns @code{#t} if that
- argument is a condition whose type's name is @var{ctype-name} or
- @code{#f} if not.
- @end deffn
- @deffn procedure condition-type condition @returns{} type-name
- @deffnx procedure condition-stuff condition @returns{} list
- Accessors for the two immutable fields of conditions.
- @end deffn
- @deffn procedure error? condition @returns{} boolean
- @deffnx procedure warning? condition @returns{} boolean
- @deffnx procedure note? condition @returns{} boolean
- @deffnx procedure syntax-error? condition @returns{} boolean
- @deffnx procedure call-error? condition @returns{} boolean
- @deffnx procedure read-error? condition @returns{} boolean
- @deffnx procedure interrupt? condition @returns{} boolean
- Condition predicates for built-in condition types.
- @end deffn
- @deffn procedure make-exception opcode reason arguments @returns{} exception
- @deffnx procedure exception? condition @returns{} boolean
- @deffnx procedure exception-opcode exception @returns{} integer-opcode
- @deffnx procedure exception-reason exception @returns{} symbol
- @deffnx procedure exception-arguments exception @returns{} list
- @dfn{Exceptions} represent run-time errors in the Scheme48 VM. They
- contain information about what opcode the VM was executing when it
- happened, what the reason for the exception occurring was, and the
- relevant arguments.
- @c @xref{VM exceptions}.
- @end deffn
- @subsection Displaying conditions
- @cindex printing conditions
- @cindex displaying conditions
- The @code{display-conditions} structure is also relevant in this
- section.
- @deffn procedure display-condition condition port @returns{} unspecified
- Prints @var{condition} to @var{port} for a user to read. For example:
- @lisp
- (display-condition (make-condition 'error
- "Foo bar baz"
- 'quux
- '(zot mumble: frotz))
- (current-output-port))
- @print{} Error: Foo bar baz
- @print{} quux
- @print{} (zot mumble: frotz)@end lisp
- @end deffn
- @defvr {method table} &disclose-condition condition @returns{} disclosed
- Method table (@pxref{Generic dispatch system}) for a generic procedure
- (not exposed) used to translate a condition object into a more readable
- format. @xref{Writer}.
- @end defvr
- @deffn procedure limited-write object port max-depth max-length @returns{} unspecified
- A utility for avoiding excessive output: prints @var{object} to
- @var{port}, but will never print more than @var{max-length} of a
- subobject's components, leaving a @code{---} after the last component,
- and won't recur further down the object graph from the vertex
- @var{object} beyond @var{max-depth}, instead printing an octothorpe
- (@code{#}).
- @lisp
- (let ((x (cons #f #f)))
- (set-car! x x)
- (set-cdr! x x)
- (limited-write x (current-output-port) 2 2))
- @print{} ((# # ---) (# # ---) ---)@end lisp
- @end deffn
|