debug-format.rkt (3574B)
1 #lang racket/base 2 (require racket/pretty) 3 (provide write-debug-file 4 load-debug-file 5 serialize-datum 6 approx-parse-state) 7 8 (define (write-debug-file file exn events) 9 (with-output-to-file file 10 (lambda () 11 (write-string "`(\n") 12 (for ([event (in-list events)]) 13 (let ([event (list (car event) (cdr event))]) 14 (pretty-write (serialize-datum* event)))) 15 (write-string ")\n") 16 (newline) 17 (write (exn-message exn)) 18 (newline) 19 (pretty-write 20 (map serialize-context-frame 21 (continuation-mark-set->context 22 (exn-continuation-marks exn))))) 23 #:exists 'replace)) 24 25 (define (quoted? x) (and (pair? x) (eq? (car x) 'quote))) 26 27 (define (serialize-datum d) 28 (list 'quasiquote (serialize-datum* d))) 29 30 (define (serialize-datum* d) 31 (define (UNQUOTE x) (list 'unquote x)) 32 (cond [(number? d) d] 33 [(boolean? d) d] 34 [(symbol? d) 35 (case d 36 ((unquote) (UNQUOTE '(quote unquote))) 37 ((unquote-splicing) (UNQUOTE '(quote unquote-splicing))) 38 (else d))] 39 [(string? d) d] 40 [(bytes? d) d] 41 [(null? d) d] 42 [(pair? d) 43 (cons (serialize-datum* (car d)) (serialize-datum* (cdr d)))] 44 [(exn? d) (UNQUOTE `(make-exn ,(exn-message d) (current-continuation-marks)))] 45 [(syntax? d) (UNQUOTE `(datum->syntax #f ',(syntax->datum d)))] 46 [(module-path-index? d) 47 (define-values (path rel) 48 (module-path-index-split d)) 49 (UNQUOTE `(module-path-index-join 50 ,(serialize-datum path) 51 ,(serialize-datum rel)))] 52 [(resolved-module-path? d) 53 (UNQUOTE `(make-resolved-module-path 54 ,(serialize-datum 55 (resolved-module-path-name d))))] 56 [(path? d) 57 (UNQUOTE `(bytes->path 58 ,(serialize-datum (path->bytes d)) 59 ,(serialize-datum (path-convention-type d))))] 60 [else 61 (eprintf "unserializable value: ~e" d) 62 `(UNSERIALIZABLE ,(format "~s" d))])) 63 64 (define (serialize-context-frame frame) 65 (cons (car frame) 66 (if (cdr frame) 67 (serialize-srcloc (cdr frame)) 68 null))) 69 70 (define (serialize-srcloc s) 71 (list (let ([src (srcloc-source s)]) 72 (cond [(path? src) (path->string src)] 73 [(string? src) src] 74 [else '?])) 75 (srcloc-line s) 76 (srcloc-column s))) 77 78 (define (load-debug-file file) 79 (parameterize ((read-accept-compiled #t)) 80 (with-input-from-file file 81 (lambda () 82 (let* ([events-expr (read)] 83 [exnmsg (read)] 84 [ctx (read)]) 85 (let* ([events (eval events-expr)] 86 [events 87 (if (andmap (lambda (e) (and (list? e) (= 2 (length e)))) events) 88 (map (lambda (l) (cons (car l) (cadr l))) events) 89 events)]) 90 (values events exnmsg ctx))))))) 91 92 (define (approx-parse-state events N) 93 (for/fold ([state null]) ([event (in-list events)] [index (in-range N)]) 94 (define (pop expect) 95 (let ([top (car state)]) 96 (unless (eq? (cadr top) expect) 97 (error "bad state on ~e: ~e" (car event) state)) 98 (cdr state))) 99 (case (car event) 100 ((enter-macro enter-prim enter-local) 101 (cons (cons index event) state)) 102 ((exit-macro) 103 (pop 'enter-macro)) 104 ((exit-prim) 105 (pop 'enter-prim)) 106 ((exit-local) 107 (pop 'enter-local)) 108 (else state))))