condition.scm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Sort-of the R6RS condition library.
  4. (define-record-type &condition
  5. (make-simple-condition)
  6. simple-condition?)
  7. (define-record-type &compound-condition
  8. (make-compound-condition components)
  9. compound-condition?
  10. (components explode-condition))
  11. (define-record-discloser &compound-condition
  12. (lambda (r)
  13. (cons 'compound-condition
  14. (explode-condition r))))
  15. (define (simple-conditions con)
  16. (cond
  17. ((simple-condition? con)
  18. (list con))
  19. ((compound-condition? con)
  20. (explode-condition con))
  21. (else
  22. (assertion-violation 'simple-conditions
  23. "not a condition"
  24. con))))
  25. (define (condition? thing)
  26. (or (simple-condition? thing)
  27. (compound-condition? thing)))
  28. (define (condition . components)
  29. (make-compound-condition
  30. (apply append
  31. (map (lambda (component)
  32. (cond
  33. ((simple-condition? component)
  34. (list component))
  35. ((compound-condition? component)
  36. (explode-condition component))
  37. (else
  38. (assertion-violation 'condition
  39. "component wasn't a condition"
  40. component))))
  41. components))))
  42. (define (condition-predicate type)
  43. (if (not (record-type<=? type &condition))
  44. (assertion-violation 'condition-predicate
  45. "not a subtype of &condition"
  46. type))
  47. (let ((simple-pred (record-predicate type)))
  48. (lambda (con)
  49. (cond
  50. ((simple-condition? con)
  51. (simple-pred con))
  52. ((compound-condition? con)
  53. (any? simple-pred (explode-condition con)))
  54. (else #f)))))
  55. (define (condition-accessor type simple-access)
  56. (if (not (record-type<=? type &condition))
  57. (assertion-violation 'condition-predicate
  58. "not a subtype of &condition"
  59. type))
  60. (let ((simple-pred (record-predicate type)))
  61. (lambda (con)
  62. (cond
  63. ((simple-condition? con)
  64. (simple-access con))
  65. ((compound-condition? con)
  66. (cond
  67. ((first simple-pred (explode-condition con))
  68. => simple-access)
  69. (else
  70. (assertion-violation '<condition-accessor>
  71. "condition isn't of type"
  72. con type))))
  73. (else
  74. (assertion-violation '<condition-accessor>
  75. "condition isn't of type"
  76. con type))))))
  77. (define-syntax define-condition-type
  78. (syntax-rules ()
  79. ((define-condition-type ?name ?supertype ?constructor ?predicate
  80. (?field1 ?accessor1) ...)
  81. (define-condition-type-helper
  82. ?name ?supertype ?constructor ?predicate
  83. ((?field1 ?accessor1) ...)
  84. ()))))
  85. (define-syntax define-condition-type-helper
  86. (syntax-rules ()
  87. ((define-condition-type-helper
  88. ?name ?supertype ?constructor ?predicate
  89. ((?field1 ?accessor1) ?rest ...)
  90. (?spec1 ...))
  91. (define-condition-type-helper
  92. ?name ?supertype ?constructor ?predicate
  93. (?rest ...)
  94. (?spec1 ... (?field1 ?accessor1 temp-condition-accessor))))
  95. ((define-condition-type-helper
  96. ?name ?supertype ?constructor ?predicate
  97. ()
  98. ((?field1 ?accessor1 ?condition-accessor1) ...))
  99. (begin
  100. (define ?name (make-record-type '?name '(?field1 ...) ?supertype))
  101. (define-record-discloser ?name
  102. (lambda (r)
  103. (list '?name (?condition-accessor1 r) ...)))
  104. (define ?constructor (record-standard-constructor ?name))
  105. (define ?predicate (condition-predicate ?name))
  106. (define ?condition-accessor1 (record-accessor ?name '?field1))
  107. ...
  108. (define ?accessor1
  109. (condition-accessor ?name ?condition-accessor1))
  110. ...))))
  111. ;; Utilities, defined locally to avoid having to load SRFI 1
  112. ;; (These need to come before the standard condition types below.)
  113. (define (first pred list)
  114. (let loop ((list list))
  115. (cond ((null? list)
  116. #f)
  117. ((pred (car list))
  118. (car list))
  119. (else
  120. (loop (cdr list))))))
  121. (define (any? proc list)
  122. (let loop ((list list))
  123. (cond ((null? list)
  124. #f)
  125. ((proc (car list))
  126. #t)
  127. (else
  128. (loop (cdr list))))))
  129. ;; Standard condition types
  130. (define-condition-type &message &condition
  131. make-message-condition message-condition?
  132. (message condition-message))
  133. (define-condition-type &warning &condition
  134. make-warning warning?)
  135. (define-condition-type &serious &condition
  136. make-serious-condition serious-condition?)
  137. (define-condition-type &error &serious
  138. make-error error?)
  139. (define-condition-type &violation &serious
  140. make-violation violation?)
  141. (define-condition-type &non-continuable &violation
  142. make-noncontinuable-violation non-continuable-violation?)
  143. (define-condition-type &implementation-restriction &violation
  144. make-implementation-restriction-violation implementation-restriction-violation?)
  145. (define-condition-type &lexical &violation
  146. make-lexical-violation lexical-violation?)
  147. (define-condition-type &syntax &violation
  148. make-syntax-violation syntax-violation?
  149. (form syntax-violation-form)
  150. (subform syntax-violation-subform))
  151. (define-condition-type &undefined &violation
  152. make-undefined-violation undefined-violation?)
  153. (define-condition-type &assertion &violation
  154. make-assertion-violation assertion-violation?)
  155. (define-condition-type &irritants &condition
  156. make-irritants-condition irritants-condition?
  157. (irritants condition-irritants))
  158. (define-condition-type &who &condition
  159. make-who-condition who-condition?
  160. (who condition-who))
  161. ; Scheme-48-specific condition types
  162. ; VM Exceptions
  163. (define-condition-type &vm-exception &serious
  164. make-vm-exception vm-exception?
  165. (opcode vm-exception-opcode) ; number
  166. (reason vm-exception-reason) ; symbol
  167. )
  168. ; OS errors (errno or Windows error codes)
  169. (define-condition-type &os-error &error
  170. make-os-error os-error?
  171. (code os-error-code))
  172. ; I/O errors
  173. (define-condition-type &i/o-error &error
  174. make-i/o-error i/o-error?)
  175. (define-condition-type &i/o-port-error &i/o-error
  176. make-i/o-port-error i/o-port-error?
  177. (port i/o-error-port))
  178. ; Decoding errors
  179. (define-condition-type &decoding-error &error
  180. make-decoding-error decoding-error?
  181. (encoding-name decoding-error-encoding-name)
  182. (bytes decoding-error-bytes)
  183. (start decoding-error-start))
  184. ; Notes
  185. (define-condition-type &note &condition
  186. make-note note?)
  187. ; Interrupts
  188. (define-condition-type &interrupt &condition
  189. make-interrupt-condition interrupt-condition?
  190. (source interrupt-source))
  191. ; Decoding a condition for printing
  192. ;; Return a symbol describing the type,
  193. ;; a symbol or string describing the source of the problem, an error
  194. ;; message or #f, and a list of other objects describing the
  195. ;; problem. Valid type symbols include:
  196. ;; ERROR, ASSERTION-VIOLATION, SYNTAX-VIOLATION, VM-EXCEPTION,
  197. ;; WARNING, SERIOUS, NOTE, INTERRUPT
  198. (define (decode-condition con)
  199. (let ((type
  200. (cond
  201. ((error? con) 'error)
  202. ((assertion-violation? con) 'assertion-violation)
  203. ((syntax-violation? con) 'syntax-violation)
  204. ((vm-exception? con) 'vm-exception)
  205. ((serious-condition? con) 'serious)
  206. ((interrupt-condition? con) 'interrupt)
  207. ((warning? con) 'warning)
  208. ((note? con) 'note)
  209. (else 'unknown)))
  210. (who
  211. (and (who-condition? con)
  212. (condition-who con)))
  213. (message
  214. (and (message-condition? con)
  215. (condition-message con)))
  216. (stuff (if (irritants-condition? con)
  217. (condition-irritants con)
  218. '()))
  219. (syntax-stuff
  220. (if (syntax-violation? con)
  221. (let ((form (syntax-violation-form con))
  222. (subform (syntax-violation-subform con)))
  223. (if subform
  224. (list form subform)
  225. (list form)))
  226. '()))
  227. (more-stuff
  228. (delete-first
  229. (lambda (con) ; make sure interesting subtypes still get printed
  230. (memq (record-type con)
  231. *covered-condition-txpes*))
  232. ;; we don't expect interesting subtypes here
  233. (delete-first
  234. vm-exception?
  235. (delete-first
  236. message-condition?
  237. (delete-first
  238. who-condition?
  239. (delete-first
  240. irritants-condition?
  241. (simple-conditions con))))))))
  242. (values type who message (append stuff syntax-stuff more-stuff))))
  243. (define (delete-first pred? l)
  244. (let recur ((l l))
  245. (cond
  246. ((null? l) l)
  247. ((pred? (car l)) (cdr l))
  248. (else
  249. (cons (car l) (recur (cdr l)))))))
  250. (define *covered-condition-txpes*
  251. (list &syntax &warning &note &interrupt &error &assertion &serious))