Commit | Line | Data |
---|---|---|
17e90c5e KN |
1 | ;;; Read-Eval-Print Loop |
2 | ||
3098986b | 3 | ;; Copyright (C) 2001, 2009, 2010 Free Software Foundation, Inc. |
17e90c5e | 4 | |
eb721799 AW |
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. | |
17e90c5e | 9 | ;; |
eb721799 | 10 | ;; This library is distributed in the hope that it will be useful, |
17e90c5e | 11 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
eb721799 AW |
12 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | ;; Lesser General Public License for more details. | |
17e90c5e | 14 | ;; |
eb721799 AW |
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 | |
17e90c5e KN |
19 | |
20 | ;;; Code: | |
21 | ||
22 | (define-module (system repl repl) | |
8239263f | 23 | #:use-module (system base syntax) |
1a1a10d3 AW |
24 | #:use-module (system base pmatch) |
25 | #:use-module (system base compile) | |
26 | #:use-module (system base language) | |
27 | #:use-module (system repl common) | |
28 | #:use-module (system repl command) | |
29 | #:use-module (system vm vm) | |
30 | #:use-module (system vm debug) | |
b93c34c0 | 31 | #:export (start-repl)) |
17e90c5e | 32 | |
3a6f6678 AW |
33 | (define meta-command-token (cons 'meta 'command)) |
34 | ||
4b2afc62 | 35 | (define (meta-reader read env) |
36fb1e06 | 36 | (lambda read-args |
4b2afc62 AW |
37 | (let ((port (if (pair? read-args) (car read-args) (current-input-port)))) |
38 | (with-input-from-port port | |
39 | (lambda () | |
40 | (let ((ch (next-char #t))) | |
41 | (cond ((eof-object? ch) | |
42 | ;; apparently sometimes even if this is eof, read will | |
43 | ;; wait on somethingorother. strange. | |
44 | ch) | |
45 | ((eqv? ch #\,) | |
46 | (read-char port) | |
47 | meta-command-token) | |
48 | (else (read port env))))))))) | |
3a6f6678 AW |
49 | |
50 | ;; repl-reader is a function defined in boot-9.scm, and is replaced by | |
51 | ;; something else if readline has been activated. much of this hoopla is | |
52 | ;; to be able to re-use the existing readline machinery. | |
b93c34c0 AW |
53 | ;; |
54 | ;; Catches read errors, returning *unspecified* in that case. | |
3a6f6678 | 55 | (define (prompting-meta-read repl) |
7b69cafd AW |
56 | (call-with-error-handling |
57 | (lambda () | |
58 | (repl-reader (lambda () (repl-prompt repl)) | |
59 | (meta-reader (language-reader (repl-language repl)) | |
60 | (current-module)))) | |
61 | #:on-error 'pass)) | |
67c4505e | 62 | |
3098986b AW |
63 | (define* (start-repl #:optional (lang (current-language)) #:key |
64 | (level (1+ (or (fluid-ref *repl-level*) -1))) | |
65 | (welcome (equal? level 0))) | |
6a01fabf AW |
66 | (let ((repl (make-repl lang)) |
67 | (status #f)) | |
3098986b AW |
68 | (if welcome |
69 | (repl-welcome repl)) | |
70 | (with-fluids ((*repl-level* level) | |
c7317bec AW |
71 | (*debug-input-port* |
72 | (or (fluid-ref *debug-input-port*) (current-input-port))) | |
73 | (*debug-output-port* | |
a0d57eed | 74 | (or (fluid-ref *debug-output-port*) (current-output-port)))) |
3098986b | 75 | (let prompt-loop () |
b93c34c0 | 76 | (let ((exp (prompting-meta-read repl))) |
3098986b AW |
77 | (cond |
78 | ((eqv? exp (if #f #f))) ; read error, pass | |
79 | ((eq? exp meta-command-token) | |
b93c34c0 | 80 | (with-error-handling (meta-command repl))) |
3098986b AW |
81 | ((eof-object? exp) |
82 | (newline) | |
83 | (set! status '())) | |
84 | (else | |
85 | ;; since the input port is line-buffered, consume up to the | |
86 | ;; newline | |
87 | (flush-to-newline) | |
b93c34c0 | 88 | (with-error-handling |
3098986b AW |
89 | (catch 'quit |
90 | (lambda () | |
91 | (call-with-values | |
92 | (lambda () | |
93 | (run-hook before-eval-hook exp) | |
94 | (start-stack #t | |
95 | (repl-eval repl (repl-parse repl exp)))) | |
96 | (lambda l | |
97 | (for-each (lambda (v) | |
98 | (run-hook before-print-hook v) | |
99 | (repl-print repl v)) | |
100 | l)))) | |
101 | (lambda (k . args) | |
102 | (set! status args)))))) | |
103 | (or status | |
104 | (begin | |
105 | (next-char #f) ;; consume trailing whitespace | |
106 | (prompt-loop)))))))) | |
17e90c5e KN |
107 | |
108 | (define (next-char wait) | |
109 | (if (or wait (char-ready?)) | |
110 | (let ((ch (peek-char))) | |
d600df9a | 111 | (cond ((eof-object? ch) ch) |
17e90c5e KN |
112 | ((char-whitespace? ch) (read-char) (next-char wait)) |
113 | (else ch))) | |
114 | #f)) | |
0d646345 AW |
115 | |
116 | (define (flush-to-newline) | |
117 | (if (char-ready?) | |
118 | (let ((ch (peek-char))) | |
119 | (if (and (not (eof-object? ch)) (char-whitespace? ch)) | |
120 | (begin | |
121 | (read-char) | |
122 | (if (not (char=? ch #\newline)) | |
123 | (flush-to-newline))))))) |