35.upstream.scm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. ;; Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights Reserved.
  2. ;;
  3. ;; Permission is hereby granted, free of charge, to any person obtaining a copy
  4. ;; of this software and associated documentation files (the "Software"), to deal
  5. ;; in the Software without restriction, including without limitation the rights
  6. ;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7. ;; copies of the Software, and to permit persons to whom the Software is
  8. ;; furnished to do so, subject to the following conditions:
  9. ;;
  10. ;; The above copyright notice and this permission notice shall be included in
  11. ;; all copies or substantial portions of the Software.
  12. ;;
  13. ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14. ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15. ;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16. ;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17. ;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18. ;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  19. ;; SOFTWARE.
  20. (define-record-type :condition-type
  21. (really-make-condition-type name supertype fields all-fields)
  22. condition-type?
  23. (name condition-type-name)
  24. (supertype condition-type-supertype)
  25. (fields condition-type-fields)
  26. (all-fields condition-type-all-fields))
  27. (define (make-condition-type name supertype fields)
  28. (if (not (symbol? name))
  29. (error "make-condition-type: name is not a symbol"
  30. name))
  31. (if (not (condition-type? supertype))
  32. (error "make-condition-type: supertype is not a condition type"
  33. supertype))
  34. (if (not
  35. (null? (lset-intersection eq?
  36. (condition-type-all-fields supertype)
  37. fields)))
  38. (error "duplicate field name" ))
  39. (really-make-condition-type name
  40. supertype
  41. fields
  42. (append (condition-type-all-fields supertype)
  43. fields)))
  44. (define-syntax define-condition-type
  45. (syntax-rules ()
  46. ((define-condition-type ?name ?supertype ?predicate
  47. (?field1 ?accessor1) ...)
  48. (begin
  49. (define ?name
  50. (make-condition-type '?name
  51. ?supertype
  52. '(?field1 ...)))
  53. (define (?predicate thing)
  54. (and (condition? thing)
  55. (condition-has-type? thing ?name)))
  56. (define (?accessor1 condition)
  57. (condition-ref (extract-condition condition ?name)
  58. '?field1))
  59. ...))))
  60. (define (condition-subtype? subtype supertype)
  61. (let recur ((subtype subtype))
  62. (cond ((not subtype) #f)
  63. ((eq? subtype supertype) #t)
  64. (else
  65. (recur (condition-type-supertype subtype))))))
  66. (define (condition-type-field-supertype condition-type field)
  67. (let loop ((condition-type condition-type))
  68. (cond ((not condition-type) #f)
  69. ((memq field (condition-type-fields condition-type))
  70. condition-type)
  71. (else
  72. (loop (condition-type-supertype condition-type))))))
  73. ; The type-field-alist is of the form
  74. ; ((<type> (<field-name> . <value>) ...) ...)
  75. (define-record-type :condition
  76. (really-make-condition type-field-alist)
  77. condition?
  78. (type-field-alist condition-type-field-alist))
  79. (define (make-condition type . field-plist)
  80. (let ((alist (let label ((plist field-plist))
  81. (if (null? plist)
  82. '()
  83. (cons (cons (car plist)
  84. (cadr plist))
  85. (label (cddr plist)))))))
  86. (if (not (lset= eq?
  87. (condition-type-all-fields type)
  88. (map car alist)))
  89. (error "condition fields don't match condition type"))
  90. (really-make-condition (list (cons type alist)))))
  91. (define (condition-has-type? condition type)
  92. (any (lambda (has-type)
  93. (condition-subtype? has-type type))
  94. (condition-types condition)))
  95. (define (condition-ref condition field)
  96. (type-field-alist-ref (condition-type-field-alist condition)
  97. field))
  98. (define (type-field-alist-ref type-field-alist field)
  99. (let loop ((type-field-alist type-field-alist))
  100. (cond ((null? type-field-alist)
  101. (error "type-field-alist-ref: field not found"
  102. type-field-alist field))
  103. ((assq field (cdr (car type-field-alist)))
  104. => cdr)
  105. (else
  106. (loop (cdr type-field-alist))))))
  107. (define (make-compound-condition condition-1 . conditions)
  108. (really-make-condition
  109. (apply append (map condition-type-field-alist
  110. (cons condition-1 conditions)))))
  111. (define (extract-condition condition type)
  112. (let ((entry (find (lambda (entry)
  113. (condition-subtype? (car entry) type))
  114. (condition-type-field-alist condition))))
  115. (if (not entry)
  116. (error "extract-condition: invalid condition type"
  117. condition type))
  118. (really-make-condition
  119. (list (cons type
  120. (map (lambda (field)
  121. (assq field (cdr entry)))
  122. (condition-type-all-fields type)))))))
  123. (define-syntax condition
  124. (syntax-rules ()
  125. ((condition (?type1 (?field1 ?value1) ...) ...)
  126. (type-field-alist->condition
  127. (list
  128. (cons ?type1
  129. (list (cons '?field1 ?value1) ...))
  130. ...)))))
  131. (define (type-field-alist->condition type-field-alist)
  132. (really-make-condition
  133. (map (lambda (entry)
  134. (cons (car entry)
  135. (map (lambda (field)
  136. (or (assq field (cdr entry))
  137. (cons field
  138. (type-field-alist-ref type-field-alist field))))
  139. (condition-type-all-fields (car entry)))))
  140. type-field-alist)))
  141. (define (condition-types condition)
  142. (map car (condition-type-field-alist condition)))
  143. (define (check-condition-type-field-alist the-type-field-alist)
  144. (let loop ((type-field-alist the-type-field-alist))
  145. (if (not (null? type-field-alist))
  146. (let* ((entry (car type-field-alist))
  147. (type (car entry))
  148. (field-alist (cdr entry))
  149. (fields (map car field-alist))
  150. (all-fields (condition-type-all-fields type)))
  151. (for-each (lambda (missing-field)
  152. (let ((supertype
  153. (condition-type-field-supertype type missing-field)))
  154. (if (not
  155. (any (lambda (entry)
  156. (let ((type (car entry)))
  157. (condition-subtype? type supertype)))
  158. the-type-field-alist))
  159. (error "missing field in condition construction"
  160. type
  161. missing-field))))
  162. (lset-difference eq? all-fields fields))
  163. (loop (cdr type-field-alist))))))
  164. (define &condition (really-make-condition-type '&condition
  165. #f
  166. '()
  167. '()))
  168. (define-condition-type &message &condition
  169. message-condition?
  170. (message condition-message))
  171. (define-condition-type &serious &condition
  172. serious-condition?)
  173. (define-condition-type &error &serious
  174. error?)