forked from awwx/ar
-
Notifications
You must be signed in to change notification settings - Fork 7
/
repl
executable file
·64 lines (59 loc) · 2.66 KB
/
repl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#lang racket/base
(require (only-in "compiler" debug? globals ac-read ac print))
; TODO test that everything works
;; http://arclanguage.org/item?id=10344
(let ((interactive (terminal-port? (current-input-port))))
(define (print-err c)
(let ((msg (string-append "error: " (exn-message c))))
(if (debug?)
; Displays the stack trace when debug? is t
((error-display-handler) msg c) ; TODO: use error port
;; http://arclanguage.org/item?id=10344
(displayln msg (current-error-port)))))
(when (and interactive (not (eq? 'windows (system-type))))
(define set-completion-function!
(dynamic-require 'readline/readline 'set-completion-function!))
(dynamic-require 'readline/rep-start #f)
(set-completion-function!
(lambda (s)
(let ((s (regexp (string-append "^" (regexp-quote s))))
(r null))
(hash-for-each (globals)
(lambda (key _)
(let ((key (symbol->string key)))
(when (regexp-match? s key)
(set! r (cons key r))))))
r))))
(let repl ()
;; This causes Ctrl+C to return to the REPL, rather than aborting.
;; Technique was taken from Racket's (read-eval-print-loop) which
;; I found in /usr/share/racket/collects/racket/private/misc.rkt
(call-with-continuation-prompt
(lambda ()
(let ((expr (if interactive
;; This is to make GNU readline work
(let ((it ((current-prompt-read))))
(if (syntax? it)
(syntax->datum it)
it))
((ac-read) (current-input-port)))))
(if (eof-object? expr)
(when interactive
(newline))
(begin (call-with-values
(lambda ()
(call-with-continuation-prompt
(lambda ()
(with-handlers ((exn:fail? print-err))
(eval (ac expr))))))
(lambda results
(when interactive
(for ((x results))
(unless (void? x)
(print write x (current-output-port))))
;(for-each (current-print) results) ; TODO use current-print
)))
;; Abort to loop. (Calling `repl' directly would not be a tail call.)
(abort-current-continuation (default-continuation-prompt-tag))))))
(default-continuation-prompt-tag)
(lambda args (repl)))))