condition.texi 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. @node Condition system
  2. @section Condition system
  3. @stindex exceptions
  4. @stindex conditions
  5. As of version 1.3 (different from all older versions), Scheme48
  6. supports two different condition systems. One of them, the original
  7. one, is a simple system where conditions are represented as tagged
  8. lists. This section documents the original one. The new condition
  9. system is [SRFI 34, 35], and there is a complicated translation layer
  10. between the old one, employed by the run-time system, and the new one,
  11. which is implemented in a layer high above that as a library, but a
  12. library which is always loaded in the usual development environment.
  13. See the [SRFI 34, 35] documents for documentation of the new condition
  14. system. [SRFI 34] is available from the @code{exceptions} structure;
  15. SRFI 35, from the @code{conditions} structure.
  16. @strong{Note:} The condition system changed in Scheme48 version 1.3.
  17. While the old one is still available, the names of the structures that
  18. implement it changed. @code{Signals} is now @code{simple-signals},
  19. and @code{conditions} is now @code{simple-conditions}. The structure
  20. that @code{signals} @emph{now} names implements the same interface,
  21. but with [SRFI 34, 35] underlying it. The structure that the name
  22. @code{conditions} @emph{now} identifies [SRFI 35]. You will have to
  23. update all old code that relied on the old @code{signals} and
  24. @code{conditions} structure either by using those structures' new
  25. names or by invasively modifying all code to use [SRFI 34, 35]. Also,
  26. the only way to completely elide the use of the SRFIs is to evaluate
  27. this in an environment with the @code{exceptions-internal} and
  28. @code{vm-exceptions} structure open:
  29. @lisp
  30. (begin (initialize-vm-exceptions! really-signal-condition)
  31. ;; INITIALIZE-VM-EXCEPTIONS! returns a very large object,
  32. ;; which we probably don't want printed at the REPL.
  33. #t)@end lisp
  34. @subsection Signalling, handling, and representing conditions
  35. @cindex conditions
  36. @cindex exceptions
  37. @cindex errors
  38. @cindex warnings
  39. @cindex signalling conditions
  40. @cindex condition types
  41. @cindex condition handlers
  42. Scheme48 provides a simple condition system.@footnote{Note, however,
  43. that Scheme48's condition system is likely to be superseded in the near
  44. future by [SRFI 34, SRFI 35].} @dfn{Conditions} are objects that
  45. describe exceptional situations. Scheme48 keeps a registry of
  46. @dfn{condition types}, which just have references to their supertypes.
  47. Conditions are simple objects that contain only two fields, the type
  48. and the type-specific data (the @dfn{stuff}). Accessor procedures
  49. should be defined for particular condition types to extract the data
  50. contained within the `stuff' fields of instances of of those condition
  51. types. Condition types are represented as symbols. @dfn{Condition
  52. handlers} are part of the system's dynamic context; they are used to
  53. handle exceptional situations when conditions are signalled that
  54. describe such exceptional situations. @dfn{Signalling} a condition
  55. signals that an exceptional situation occurred and invokes the current
  56. condition handler on the condition.
  57. Scheme48's condition system is split up into three structures:
  58. @table @code
  59. @item simple-signals
  60. Exports procedures to signal conditions and construct conditions, as
  61. well as some utilities for common kinds of conditions.
  62. @item handle
  63. Exports facilities for handling signalled conditions.
  64. @item simple-conditions
  65. The system of representing conditions as objects.
  66. @end table
  67. @stindex simple-signals
  68. The @code{simple-signals} structure exports these procedures:
  69. @deffn procedure make-condition type-name stuff @returns{} condition
  70. The condition object constructor.
  71. @end deffn
  72. @deffn procedure signal-condition condition @returns{} values (may not return)
  73. @deffnx procedure signal type-name stuff @dots{} @returns{} values (may not return)
  74. @code{Signal-condition} signals the given condition. @code{Signal} is
  75. a convenience atop the common conjunction of @code{signal-condition}
  76. and @code{make-condition}: it constructs a condition with the given
  77. type name and stuff, whereafter it signals that condition with
  78. @code{signal-condition}.
  79. @end deffn
  80. @deffn procedure error message irritant @dots{} @returns{} values (may not return)
  81. @deffnx procedure warn message irritant @dots{} @returns{} values (may not return)
  82. @deffnx procedure syntax-error message irritant @dots{} @returns{} expression (may not return)
  83. @deffnx procedure call-error message irritant @dots{} @returns{} values (may not return)
  84. @deffnx procedure note message irritant @dots{} @returns{} values (may not return)
  85. Conveniences for signalling standard condition types. These procedures
  86. generally either do not return or return an unspecified value, unless
  87. specified to by a user of the debugger. @code{Syntax-error} returns
  88. the expression @code{(quote syntax-error)}, if the condition handler
  89. returns to @code{syntax-error} in the first place.
  90. @cindex error messages
  91. @cindex condition messages
  92. By convention, the message should be lowercased (@ie{} the first word
  93. should not be capitalized), and it should not end with punctuation.
  94. The message is typically not a complete sentence. For example, these
  95. all follow Scheme48's convention:
  96. @itemize @w{}
  97. @item argument type error
  98. @item wrong number of arguments
  99. @item invalid syntax
  100. @item ill-typed right-hand side
  101. @item out of memory, unable to continue
  102. @end itemize
  103. These, on the other hand, do not follow the convention and should be
  104. avoided:
  105. @itemize @w{}
  106. @item Argument type error:
  107. @item An argument of the wrong type was passed.
  108. @item possible type mismatch:
  109. @item Luser is an idiot!
  110. @end itemize
  111. Elaboration on a message is performed usually by wrapping an irritant
  112. in a descriptive list. For example, one might write:
  113. @lisp
  114. (error "invalid argument"
  115. '(not a pair)
  116. `(while calling ,frobbotz)
  117. `(received ,object))@end lisp
  118. @noindent
  119. This might be printed as:
  120. @example
  121. Error: invalid argument
  122. (not a pair)
  123. (while calling #@{Procedure 123 (frobbotz in ...)@})
  124. (received #(a b c d))@end example
  125. @end deffn
  126. @cindex installing condition handlers
  127. @stindex handle
  128. The @code{handle} structure exports the following procedures:
  129. @deffn procedure with-handler handler thunk @returns{} values
  130. Sets up @var{handler} as the condition handler for the dynamic extent
  131. of @var{thunk}. @var{Handler} should be a procedure of two arguments:
  132. the condition that was signalled and a procedure of zero arguments that
  133. propagates the condition up to the next dynamically enclosing handler.
  134. When a condition is signalled, @var{handler} is tail-called from the
  135. point that the condition was signalled at. Note that, because
  136. @var{handler} is tail-called at that point, it will @emph{return} to
  137. that point also.
  138. @strong{Warning:} @code{With-handler} is potentially very dangerous.
  139. If an exception occurs and a condition is raised in the handler, the
  140. handler itself will be called with that new condition! Furthermore,
  141. the handler may accidentally return to an unexpecting signaller, which
  142. can cause very confusing errors. Be careful with @code{with-handler};
  143. to be perfectly safe, it might be a good idea to throw back out to
  144. where the handler was initially installed before doing anything:
  145. @lisp
  146. ((call-with-current-continuation
  147. (lambda (k)
  148. (lambda ()
  149. (with-handler (lambda (c propagate)
  150. (k (lambda () @var{handler body})))
  151. (lambda () @var{body}))))))@end lisp
  152. @end deffn
  153. @deffn procedure ignore-errors thunk @returns{} values or condition
  154. @deffnx procedure report-errors-as-warnings thunk message irritant @dots{} @returns{} values
  155. @code{Ignore-errors} sets up a condition handler that will return error
  156. conditions to the point where @code{ignore-errors} was called, and
  157. propagate all other conditions. If no condition is signalled during
  158. the dynamic extent of @var{thunk}, @code{ignore-errors} simply returns
  159. whatever @var{thunk} returned. @code{Report-errors-as-warnings}
  160. downgrades errors to warnings while executing @var{thunk}. If an error
  161. occurs, a warning is signalled with the given message, and a list of
  162. irritants constructed by adding the error condition to the end of the
  163. list @var{irritant} @dots{}.
  164. @end deffn
  165. @cindex conditions
  166. @cindex condition types
  167. @stindex simple-conditions
  168. Finally, the @code{simple-conditions} structure defines the condition
  169. type system. (Note that conditions themselves are constructed only by
  170. @code{make-condition} (and @code{signal}) from the
  171. @code{simple-signals} structure.) Conditions are very basic values
  172. that have only two universally defined fields: the type and the stuff.
  173. The type is a symbol denoting a condition type. The type is specified
  174. in the first argument to @code{make-condition} or @code{signal}. The
  175. stuff field contains whatever a particular condition type stores in
  176. conditions of that type. The stuff field is always a list; it is
  177. created from the arguments after the first to @code{make-condition} or
  178. @code{signal}. Condition types are denoted by symbols, kept in a
  179. global registry that maps condition type names to their supertype
  180. names.
  181. @deffn procedure define-condition-type name supertype-names @returns{} unspecified
  182. Registers the symbol @var{name} as a condition type. Its supertypes
  183. are named in the list @var{supertype-names}.
  184. @end deffn
  185. @deffn procedure condition-predicate ctype-name @returns{} predicate
  186. Returns a procedure of one argument that returns @code{#t} if that
  187. argument is a condition whose type's name is @var{ctype-name} or
  188. @code{#f} if not.
  189. @end deffn
  190. @deffn procedure condition-type condition @returns{} type-name
  191. @deffnx procedure condition-stuff condition @returns{} list
  192. Accessors for the two immutable fields of conditions.
  193. @end deffn
  194. @deffn procedure error? condition @returns{} boolean
  195. @deffnx procedure warning? condition @returns{} boolean
  196. @deffnx procedure note? condition @returns{} boolean
  197. @deffnx procedure syntax-error? condition @returns{} boolean
  198. @deffnx procedure call-error? condition @returns{} boolean
  199. @deffnx procedure read-error? condition @returns{} boolean
  200. @deffnx procedure interrupt? condition @returns{} boolean
  201. Condition predicates for built-in condition types.
  202. @end deffn
  203. @deffn procedure make-exception opcode reason arguments @returns{} exception
  204. @deffnx procedure exception? condition @returns{} boolean
  205. @deffnx procedure exception-opcode exception @returns{} integer-opcode
  206. @deffnx procedure exception-reason exception @returns{} symbol
  207. @deffnx procedure exception-arguments exception @returns{} list
  208. @dfn{Exceptions} represent run-time errors in the Scheme48 VM. They
  209. contain information about what opcode the VM was executing when it
  210. happened, what the reason for the exception occurring was, and the
  211. relevant arguments.
  212. @c @xref{VM exceptions}.
  213. @end deffn
  214. @subsection Displaying conditions
  215. @cindex printing conditions
  216. @cindex displaying conditions
  217. The @code{display-conditions} structure is also relevant in this
  218. section.
  219. @deffn procedure display-condition condition port @returns{} unspecified
  220. Prints @var{condition} to @var{port} for a user to read. For example:
  221. @lisp
  222. (display-condition (make-condition 'error
  223. "Foo bar baz"
  224. 'quux
  225. '(zot mumble: frotz))
  226. (current-output-port))
  227. @print{} Error: Foo bar baz
  228. @print{} quux
  229. @print{} (zot mumble: frotz)@end lisp
  230. @end deffn
  231. @defvr {method table} &disclose-condition condition @returns{} disclosed
  232. Method table (@pxref{Generic dispatch system}) for a generic procedure
  233. (not exposed) used to translate a condition object into a more readable
  234. format. @xref{Writer}.
  235. @end defvr
  236. @deffn procedure limited-write object port max-depth max-length @returns{} unspecified
  237. A utility for avoiding excessive output: prints @var{object} to
  238. @var{port}, but will never print more than @var{max-length} of a
  239. subobject's components, leaving a @code{---} after the last component,
  240. and won't recur further down the object graph from the vertex
  241. @var{object} beyond @var{max-depth}, instead printing an octothorpe
  242. (@code{#}).
  243. @lisp
  244. (let ((x (cons #f #f)))
  245. (set-car! x x)
  246. (set-cdr! x x)
  247. (limited-write x (current-output-port) 2 2))
  248. @print{} ((# # ---) (# # ---) ---)@end lisp
  249. @end deffn