~ chicken-core (chicken-5) /repl.scm
Trap1;;;; repl.scm - CHICKEN's read/eval/print loop
2;
3; Copyright (c) 2008-2022, The CHICKEN Team
4; Copyright (c) 2000-2007, Felix L. Winkelmann
5; All rights reserved.
6;
7; Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
8; conditions are met:
9;
10; Redistributions of source code must retain the above copyright notice, this list of conditions and the following
11; disclaimer.
12; Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
13; disclaimer in the documentation and/or other materials provided with the distribution.
14; Neither the name of the author nor the names of its contributors may be used to endorse or promote
15; products derived from this software without specific prior written permission.
16;
17; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS
18; OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
19; AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
20; CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22; SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23; THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24; OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25; POSSIBILITY OF SUCH DAMAGE.
26
27(declare
28 (unit repl)
29 (uses eval)
30 (not inline ##sys#repl-read-hook ##sys#repl-print-hook ##sys#read-prompt-hook))
31
32(module chicken.repl
33 (quit repl repl-prompt reset reset-handler)
34
35(import scheme
36 chicken.base
37 chicken.eval
38 chicken.foreign
39 chicken.load
40 chicken.syntax)
41
42(include "common-declarations.scm")
43
44(define ##sys#repl-print-length-limit #f)
45(define ##sys#repl-read-hook #f)
46(define ##sys#repl-recent-call-chain #f) ; used in csi for ,c command
47
48(define (##sys#repl-print-hook x port)
49 (##sys#with-print-length-limit ##sys#repl-print-length-limit (cut ##sys#print x #t port))
50 (##sys#write-char-0 #\newline port))
51
52(define (quit-hook result) (exit))
53(define (quit #!optional result) (quit-hook result))
54
55(define reset-handler ##sys#reset-handler)
56(define (reset) ((reset-handler)))
57
58(define repl-prompt
59 (make-parameter (lambda () "#;> ")))
60
61(define ##sys#read-prompt-hook
62 (let ((repl-prompt repl-prompt))
63 (lambda ()
64 (##sys#print ((repl-prompt)) #f ##sys#standard-output)
65 (##sys#flush-output ##sys#standard-output))))
66
67(define (##sys#resize-trace-buffer i)
68 (##sys#check-fixnum i)
69 (##core#inline "C_resize_trace_buffer" i))
70
71(define repl
72 (let ((eval eval)
73 (call-with-current-continuation call-with-current-continuation)
74 (string-append string-append))
75 (lambda (#!optional (evaluator eval))
76
77 (define (write-err xs)
78 (for-each (cut ##sys#repl-print-hook <> ##sys#standard-error) xs))
79
80 (define (write-results xs)
81 (cond ((null? xs)
82 (##sys#print "; no values\n" #f ##sys#standard-output))
83 ((not (eq? (##core#undefined) (car xs)))
84 (for-each (cut ##sys#repl-print-hook <> ##sys#standard-output) xs)
85 (when (pair? (cdr xs))
86 (##sys#print
87 (string-append "; " (##sys#number->string (length xs)) " values\n")
88 #f ##sys#standard-output)))))
89
90 (let ((stdin ##sys#standard-input)
91 (stdout ##sys#standard-output)
92 (stderr ##sys#standard-error)
93 (ehandler (##sys#error-handler))
94 (rhandler (##sys#reset-handler))
95 (notices ##sys#notices-enabled)
96 (lv #f)
97 (qh quit-hook)
98 (uie ##sys#unbound-in-eval))
99
100 (define (saveports)
101 (set! stdin ##sys#standard-input)
102 (set! stdout ##sys#standard-output)
103 (set! stderr ##sys#standard-error))
104
105 (define (resetports)
106 (set! ##sys#standard-input stdin)
107 (set! ##sys#standard-output stdout)
108 (set! ##sys#standard-error stderr))
109
110 (call-with-current-continuation
111 (lambda (k)
112 (##sys#dynamic-wind
113 (lambda ()
114 (set! lv (load-verbose))
115 (set! quit-hook (lambda (result) (k result)))
116 (load-verbose #t)
117 (set! ##sys#notices-enabled #t)
118 (##sys#error-handler
119 (lambda (msg . args)
120 (resetports)
121 (##sys#print "\nError" #f ##sys#standard-error)
122 (when msg
123 (##sys#print ": " #f ##sys#standard-error)
124 (##sys#print msg #f ##sys#standard-error))
125 (if (and (pair? args) (null? (cdr args)))
126 (begin
127 (##sys#print ": " #f ##sys#standard-error)
128 (write-err args))
129 (begin
130 (##sys#write-char-0 #\newline ##sys#standard-error)
131 (write-err args)))
132 (set! ##sys#repl-recent-call-chain
133 (let ((ct (or (and-let* ((lexn ##sys#last-exception) ;XXX not really right
134 ((##sys#structure? lexn 'condition))
135 (a (member '(exn . call-chain) (##sys#slot lexn 2))))
136 (cadr a))
137 (get-call-chain 0 ##sys#current-thread))))
138 (##sys#really-print-call-chain
139 ##sys#standard-error ct
140 "\n\tCall history:\n")
141 ct))
142 (flush-output ##sys#standard-error))))
143 (lambda ()
144 (let loop ()
145 (saveports)
146 (call-with-current-continuation
147 (lambda (c)
148 (##sys#reset-handler
149 (lambda ()
150 (set! ##sys#read-error-with-line-number #f)
151 (resetports)
152 (c #f)))))
153 (##sys#read-prompt-hook)
154 ;; OBSOLETE - after bootstrapping we can get rid of this explicit namespacing
155 (let ((exp ((or ##sys#repl-read-hook chicken.syntax#read-with-source-info))))
156 (unless (eof-object? exp)
157 (when (eq? #\newline (##sys#peek-char-0 ##sys#standard-input))
158 (##sys#read-char-0 ##sys#standard-input))
159 (foreign-code "C_clear_trace_buffer();")
160 (set! ##sys#unbound-in-eval '())
161 (receive result (evaluator exp)
162 (when (and ##sys#warnings-enabled (pair? ##sys#unbound-in-eval))
163 (let loop ((vars ##sys#unbound-in-eval)
164 (u '()))
165 (cond ((null? vars)
166 (when (pair? u)
167 (when ##sys#notices-enabled
168 (##sys#notice
169 "the following toplevel variables are referenced but unbound:\n")
170 (for-each
171 (lambda (v)
172 (##sys#print " " #f ##sys#standard-error)
173 (##sys#print (car v) #t ##sys#standard-error)
174 (when (cdr v)
175 (##sys#print " (in " #f ##sys#standard-error)
176 (##sys#print (cdr v) #t ##sys#standard-error)
177 (##sys#write-char-0 #\) ##sys#standard-error))
178 (##sys#write-char-0 #\newline ##sys#standard-error))
179 u)
180 (##sys#flush-output ##sys#standard-error))))
181 ((or (memq (caar vars) u)
182 (##core#inline "C_u_i_namespaced_symbolp" (caar vars))
183 (##sys#symbol-has-toplevel-binding? (caar vars)))
184 (loop (cdr vars) u))
185 (else (loop (cdr vars) (cons (car vars) u)))) 9))
186 (write-results result)
187 (loop))))))
188 (lambda ()
189 (load-verbose lv)
190 (set! quit-hook qh)
191 (set! ##sys#notices-enabled notices)
192 (set! ##sys#unbound-in-eval uie)
193 (##sys#error-handler ehandler)
194 (##sys#reset-handler rhandler))))))))))