Commit | Line | Data |
---|---|---|
33df2ec7 AW |
1 | ;;; Error handling in the REPL |
2 | ||
3 | ;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc. | |
4 | ||
5 | ;; This library is free software; you can redistribute it and/or | |
6 | ;; modify it under the terms of the GNU Lesser General Public | |
7 | ;; License as published by the Free Software Foundation; either | |
8 | ;; version 3 of the License, or (at your option) any later version. | |
9 | ;; | |
10 | ;; This library is distributed in the hope that it will be useful, | |
11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | ;; Lesser General Public License for more details. | |
14 | ;; | |
15 | ;; You should have received a copy of the GNU Lesser General Public | |
16 | ;; License along with this library; if not, write to the Free Software | |
17 | ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | |
18 | ;; 02110-1301 USA | |
19 | ||
20 | ;;; Code: | |
21 | ||
22 | (define-module (system repl error-handling) | |
23 | #:use-module (system base pmatch) | |
24 | #:use-module (system repl debug) | |
25 | #:export (call-with-error-handling | |
26 | with-error-handling)) | |
27 | ||
28 | ||
29 | \f | |
30 | ||
31 | ;;; | |
32 | ;;; Error handling via repl debugging | |
33 | ;;; | |
34 | ||
35 | (define* (call-with-error-handling thunk #:key | |
36 | (on-error 'debug) (post-error 'catch) | |
37 | (pass-keys '(quit))) | |
38 | (let ((in (current-input-port)) | |
39 | (out (current-output-port)) | |
40 | (err (current-error-port))) | |
41 | (define (with-saved-ports thunk) | |
42 | (with-input-from-port in | |
43 | (lambda () | |
44 | (with-output-to-port out | |
45 | (lambda () | |
46 | (with-error-to-port err | |
47 | thunk)))))) | |
48 | ||
49 | (catch #t | |
50 | (lambda () (%start-stack #t thunk)) | |
51 | ||
52 | (case post-error | |
53 | ((catch) | |
54 | (lambda (key . args) | |
55 | (if (memq key pass-keys) | |
56 | (apply throw key args) | |
57 | (begin | |
58 | (pmatch args | |
59 | ((,subr ,msg ,args . ,rest) | |
60 | (with-saved-ports | |
61 | (lambda () | |
62 | (run-hook before-error-hook) | |
63 | (display-error #f err subr msg args rest) | |
64 | (run-hook after-error-hook) | |
65 | (force-output err)))) | |
66 | (else | |
67 | (format err "\nERROR: uncaught throw to `~a', args: ~a\n" | |
68 | key args))) | |
69 | (if #f #f))))) | |
70 | (else | |
71 | (if (procedure? post-error) | |
72 | post-error ; a handler proc | |
73 | (error "Unknown post-error strategy" post-error)))) | |
74 | ||
75 | (case on-error | |
76 | ((debug) | |
77 | (lambda (key . args) | |
867961f9 AW |
78 | (let* ((tag (and (pair? (fluid-ref %stacks)) |
79 | (cdar (fluid-ref %stacks)))) | |
80 | (stack (narrow-stack->vector | |
81 | (make-stack #t) | |
82 | ;; Cut three frames from the top of the stack: | |
83 | ;; make-stack, this one, and the throw handler. | |
84 | 3 | |
85 | ;; Narrow the end of the stack to the most recent | |
86 | ;; start-stack. | |
87 | tag | |
88 | ;; And one more frame, because %start-stack invoking | |
89 | ;; the start-stack thunk has its own frame too. | |
90 | 0 (and tag 1))) | |
91 | (debug (make-debug stack 0))) | |
33df2ec7 AW |
92 | (with-saved-ports |
93 | (lambda () | |
94 | (pmatch args | |
95 | ((,subr ,msg ,args . ,rest) | |
867961f9 AW |
96 | (display-error (vector-ref stack 0) (current-output-port) |
97 | subr msg args rest)) | |
33df2ec7 AW |
98 | (else |
99 | (format #t "Throw to key `~a' with args `~s'." key args))) | |
867961f9 AW |
100 | (format #t "Entering a new prompt. ") |
101 | (format #t "Type `,bt' for a backtrace or `,q' to continue.\n") | |
102 | ((@ (system repl repl) start-repl) #:debug debug)))))) | |
33df2ec7 AW |
103 | ((pass) |
104 | (lambda (key . args) | |
105 | ;; fall through to rethrow | |
106 | #t)) | |
107 | (else | |
108 | (if (procedure? on-error) | |
109 | on-error ; pre-unwind handler | |
110 | (error "Unknown on-error strategy" on-error))))))) | |
111 | ||
112 | (define-syntax with-error-handling | |
113 | (syntax-rules () | |
114 | ((_ form) | |
115 | (call-with-error-handling (lambda () form))))) |