Skip to content

Commit dfadee5

Browse files
mfikesswannodette
authored andcommitted
CLJS-1572: REPL doesn't give error for expressions with too many right parentheses.
Take extra care to preserve the state of *in* so that anything beyond the first form remains for reading. This fundamentally makes the ClojureScript REPL behave like the Clojure REPL. In particular, it allows entering multiple forms on a single line (which will be evaluated serially). It also means that if malformed input lies beyond the initial form, it will be read and will cause an exception (just like in the Clojure REPL). The bulk of the complexity in this commit has to do with the case where a new line-numbering reader is established, so that errors in forms can be associated with line numbers, starting with line 1 being the first line of the form. This requires a little extra handling because the source-logging-push-back-reader introduces an extra 1-character buffer which must be transferred back to the original (pre-bound) *in*, otherwise things like an unmatched extra paren right after a well-formed form won't be detected (as the paren would be in the 1-char buffer and discarded.) Also, a Java PushbackReader needs to be eliminated, as it causes things to fail to behave like the Clojure REPL.
1 parent 7c7d6b7 commit dfadee5

File tree

1 file changed

+13
-9
lines changed

1 file changed

+13
-9
lines changed

src/main/clojure/cljs/repl.cljc

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -97,14 +97,18 @@
9797
([request-prompt request-exit]
9898
(repl-read request-prompt request-exit *repl-opts*))
9999
([request-prompt request-exit opts]
100-
(binding [*in* (if (true? (:source-map-inline opts))
101-
((:reader opts))
102-
*in*)]
103-
(or ({:line-start request-prompt :stream-end request-exit}
104-
(skip-whitespace *in*))
105-
(let [input (reader/read {:read-cond :allow :features #{:cljs}} *in*)]
106-
(skip-if-eol *in*)
107-
input)))))
100+
(let [current-in *in*
101+
bind-in? (true? (:source-map-inline opts))]
102+
(binding [*in* (if bind-in?
103+
((:reader opts))
104+
*in*)]
105+
(or ({:line-start request-prompt :stream-end request-exit}
106+
(skip-whitespace *in*))
107+
(let [input (reader/read {:read-cond :allow :features #{:cljs}} *in*)]
108+
;; Transfer 1-char buffer to original *in*
109+
(readers/unread current-in (readers/read-char *in*))
110+
(skip-if-eol (if bind-in? current-in *in*))
111+
input))))))
108112

109113
;; =============================================================================
110114
;; CLJS Specifics
@@ -745,7 +749,7 @@
745749
print println
746750
caught repl-caught
747751
reader #(readers/source-logging-push-back-reader
748-
(PushbackReader. (io/reader *in*))
752+
*in*
749753
1 "NO_SOURCE_FILE")
750754
print-no-newline print
751755
source-map-inline true

0 commit comments

Comments
 (0)