;;;; condition-utils.scm -*- Scheme -*- ;;;; Kon Lovett, Jul '18 ;;;; Kon Lovett, May '17 ;;;; Kon Lovett, Aug '14 ;;;; Kon Lovett, Jun '13 ;;;; Kon Lovett, Aug '10 ;;;; Kon Lovett, Apr '09 (declare (bound-to-procedure ##sys#really-print-call-chain) ) (module condition-utils (;export ; call-chain? ; condition-irritants ; make-condition+ condition-predicate* condition-property-accessor* (make-condition-predicate condition-predicate*) (make-condition-property-accessor condition-property-accessor*) ; write-condition) (import scheme) (import (chicken base)) (import (chicken condition)) (import (chicken syntax)) (import (chicken type)) (import (only (chicken string) ->string)) (import (only (chicken format) format)) (import (only (chicken port) call-with-output-string)) (import (only (srfi 69) make-hash-table hash-table-ref/default hash-table-set!)) (import (only (srfi 1) concatenate)) (import condition-utils-support) ;; (: condition-irritants (condition --> list)) (: make-condition+ (#!rest --> condition)) (: condition-predicate* (symbol -> (* -> boolean : condition))) (: condition-property-accessor* (symbol symbol #!optional * -> (procedure (condition) *))) (: call-chain? (* -> boolean : (list-of vector))) (: write-condition (condition #!optional output-port string -> void)) (: condition-property->string (condition symbol symbol * -> string)) ;; ; Symbols are convention. Any object supported. #; ;UNUSED (define (check-kind loc obj) #;(check-symbol loc obj 'property-kind) obj ) #; ;UNUSED (define (check-property-tag loc obj) #;(check-symbol loc obj 'property-tag) obj ) ;;; ;condition->plist ;condition->alist ;; All condition properties ;((exn (arguments (test)) (message "test") (location test)) (test) (extra (test 23))) ;=> ;((arguments (test)) (message "test") (location test) (test 23)) ; (define (condition-irritants cnd) ;indifferent to plist vs alist representation of condition-properties ;from 'condition->list'. (concatenate (map cdr (condition->list cnd))) ) ;; Condition from condition expression; composite when indicated (define (make-condition+ . cnds) (let ( (ls (expand-property-conditions cnds)) ) (if (null? (cdr ls)) (car ls) (apply make-composite-condition ls) ) ) ) ;; memeoized condition-predicate ctor (define condition-predicate* (let ((+preds+ (make-hash-table eq?))) (lambda (kind) #;(check-kind 'condition-predicate* kind) (or (hash-table-ref/default +preds+ kind #f) (let ( (pred (condition-predicate kind)) ) (hash-table-set! +preds+ kind pred) pred ) ) ) ) ) ;; create composite condition-predicate ;should this be a procedure? ;kinda ugly when procedural since needs to loop over kinds (define-syntax make-condition-predicate (syntax-rules () ((_ ?kind0 ...) (lambda (obj) (and ((condition-predicate* '?kind0) obj) ... ) ) ) ) ) ;; memeoized condition-property-accessor ctor (define condition-property-accessor* (let ( (+getters+ (make-hash-table eq?)) ) (lambda (kind prop #!optional dflt) #;(check-kind 'condition-property-accessor* kind) #;(check-property-tag 'condition-property-accessor* prop) (or (hash-table-ref/default +getters+ kind #f) (let ( (key (cons kind prop)) (getter (condition-property-accessor kind prop dflt)) ) (hash-table-set! +getters+ key getter) getter ) ) ) ) ) ;; create condition-property-accessor w/ "default" default ;should this be a procedure? (define-syntax make-condition-property-accessor (syntax-rules () ; ((_ ?kind ?prop) (make-condition-property-accessor ?kind ?prop #f) ) ; ((_ ?kind ?prop ?dflt) (condition-property-accessor* '?kind '?prop ?dflt) ) ) ) ;; (define (call-chain? x) ;(or (null? x) (and (proper-list? x) (every vector? x))) (or (null? x) ;chain could be empty (and (pair? x) (vector? (car x)))) ) (define (write-condition cnd #!optional (port (current-output-port)) (header "Error")) (format port "~A: ~A" header (call-with-output-string (lambda (p) (write-condition-list (condition->list cnd) p header)))) ) ;;; ;; (define (condition-property->string cnd kind prop #!optional (def "")) (->string ((condition-property-accessor kind prop def) cnd)) ) ;; #; ;UNUSED (define (exn-prop->string prop) (condition-property->string cnd 'exn prop) ) #; ;UNUSED (define (write-error-message cnd port header) (format port "~%~A(~A) ~A: ~A~%" header (exn-prop->string 'location) (exn-prop->string 'message) (exn-prop->string 'arguments)) ) ;; #; ;UNUSED (define (subheader-string header) (string-append (make-string (- (string-length header) 1) #\space) "+") ) ) ;module condition-utils