123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- ;; Copyright (C) Richard Kelsey, Michael Sperber (2002). All Rights Reserved.
- ;;
- ;; Permission is hereby granted, free of charge, to any person obtaining a copy
- ;; of this software and associated documentation files (the "Software"), to deal
- ;; in the Software without restriction, including without limitation the rights
- ;; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- ;; copies of the Software, and to permit persons to whom the Software is
- ;; furnished to do so, subject to the following conditions:
- ;;
- ;; The above copyright notice and this permission notice shall be included in
- ;; all copies or substantial portions of the Software.
- ;;
- ;; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- ;; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- ;; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- ;; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- ;; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- ;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- ;; SOFTWARE.
- (define-record-type :condition-type
- (really-make-condition-type name supertype fields all-fields)
- condition-type?
- (name condition-type-name)
- (supertype condition-type-supertype)
- (fields condition-type-fields)
- (all-fields condition-type-all-fields))
- (define (make-condition-type name supertype fields)
- (if (not (symbol? name))
- (error "make-condition-type: name is not a symbol"
- name))
- (if (not (condition-type? supertype))
- (error "make-condition-type: supertype is not a condition type"
- supertype))
- (if (not
- (null? (lset-intersection eq?
- (condition-type-all-fields supertype)
- fields)))
- (error "duplicate field name" ))
- (really-make-condition-type name
- supertype
- fields
- (append (condition-type-all-fields supertype)
- fields)))
- (define-syntax define-condition-type
- (syntax-rules ()
- ((define-condition-type ?name ?supertype ?predicate
- (?field1 ?accessor1) ...)
- (begin
- (define ?name
- (make-condition-type '?name
- ?supertype
- '(?field1 ...)))
- (define (?predicate thing)
- (and (condition? thing)
- (condition-has-type? thing ?name)))
- (define (?accessor1 condition)
- (condition-ref (extract-condition condition ?name)
- '?field1))
- ...))))
- (define (condition-subtype? subtype supertype)
- (let recur ((subtype subtype))
- (cond ((not subtype) #f)
- ((eq? subtype supertype) #t)
- (else
- (recur (condition-type-supertype subtype))))))
- (define (condition-type-field-supertype condition-type field)
- (let loop ((condition-type condition-type))
- (cond ((not condition-type) #f)
- ((memq field (condition-type-fields condition-type))
- condition-type)
- (else
- (loop (condition-type-supertype condition-type))))))
- ; The type-field-alist is of the form
- ; ((<type> (<field-name> . <value>) ...) ...)
- (define-record-type :condition
- (really-make-condition type-field-alist)
- condition?
- (type-field-alist condition-type-field-alist))
- (define (make-condition type . field-plist)
- (let ((alist (let label ((plist field-plist))
- (if (null? plist)
- '()
- (cons (cons (car plist)
- (cadr plist))
- (label (cddr plist)))))))
- (if (not (lset= eq?
- (condition-type-all-fields type)
- (map car alist)))
- (error "condition fields don't match condition type"))
- (really-make-condition (list (cons type alist)))))
- (define (condition-has-type? condition type)
- (any (lambda (has-type)
- (condition-subtype? has-type type))
- (condition-types condition)))
- (define (condition-ref condition field)
- (type-field-alist-ref (condition-type-field-alist condition)
- field))
- (define (type-field-alist-ref type-field-alist field)
- (let loop ((type-field-alist type-field-alist))
- (cond ((null? type-field-alist)
- (error "type-field-alist-ref: field not found"
- type-field-alist field))
- ((assq field (cdr (car type-field-alist)))
- => cdr)
- (else
- (loop (cdr type-field-alist))))))
- (define (make-compound-condition condition-1 . conditions)
- (really-make-condition
- (apply append (map condition-type-field-alist
- (cons condition-1 conditions)))))
- (define (extract-condition condition type)
- (let ((entry (find (lambda (entry)
- (condition-subtype? (car entry) type))
- (condition-type-field-alist condition))))
- (if (not entry)
- (error "extract-condition: invalid condition type"
- condition type))
- (really-make-condition
- (list (cons type
- (map (lambda (field)
- (assq field (cdr entry)))
- (condition-type-all-fields type)))))))
- (define-syntax condition
- (syntax-rules ()
- ((condition (?type1 (?field1 ?value1) ...) ...)
- (type-field-alist->condition
- (list
- (cons ?type1
- (list (cons '?field1 ?value1) ...))
- ...)))))
- (define (type-field-alist->condition type-field-alist)
- (really-make-condition
- (map (lambda (entry)
- (cons (car entry)
- (map (lambda (field)
- (or (assq field (cdr entry))
- (cons field
- (type-field-alist-ref type-field-alist field))))
- (condition-type-all-fields (car entry)))))
- type-field-alist)))
- (define (condition-types condition)
- (map car (condition-type-field-alist condition)))
- (define (check-condition-type-field-alist the-type-field-alist)
- (let loop ((type-field-alist the-type-field-alist))
- (if (not (null? type-field-alist))
- (let* ((entry (car type-field-alist))
- (type (car entry))
- (field-alist (cdr entry))
- (fields (map car field-alist))
- (all-fields (condition-type-all-fields type)))
- (for-each (lambda (missing-field)
- (let ((supertype
- (condition-type-field-supertype type missing-field)))
- (if (not
- (any (lambda (entry)
- (let ((type (car entry)))
- (condition-subtype? type supertype)))
- the-type-field-alist))
- (error "missing field in condition construction"
- type
- missing-field))))
- (lset-difference eq? all-fields fields))
- (loop (cdr type-field-alist))))))
- (define &condition (really-make-condition-type '&condition
- #f
- '()
- '()))
- (define-condition-type &message &condition
- message-condition?
- (message condition-message))
- (define-condition-type &serious &condition
- serious-condition?)
- (define-condition-type &error &serious
- error?)
|