Permalink
Browse files

CLJS-1572: REPL doesn't give error for expressions with too many righ…

…t 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.
  • Loading branch information...
mfikes authored and swannodette committed Feb 22, 2016
1 parent 7c7d6b7 commit dfadee51fa3fad58b7c4cf7de532e9a10e0f802f
Showing with 13 additions and 9 deletions.
  1. +13 −9 src/main/clojure/cljs/repl.cljc
@@ -97,14 +97,18 @@
([request-prompt request-exit]
(repl-read request-prompt request-exit *repl-opts*))
([request-prompt request-exit opts]
(binding [*in* (if (true? (:source-map-inline opts))
((:reader opts))
*in*)]
(or ({:line-start request-prompt :stream-end request-exit}
(skip-whitespace *in*))
(let [input (reader/read {:read-cond :allow :features #{:cljs}} *in*)]
(skip-if-eol *in*)
input)))))
(let [current-in *in*
bind-in? (true? (:source-map-inline opts))]
(binding [*in* (if bind-in?
((:reader opts))
*in*)]
(or ({:line-start request-prompt :stream-end request-exit}
(skip-whitespace *in*))
(let [input (reader/read {:read-cond :allow :features #{:cljs}} *in*)]
;; Transfer 1-char buffer to original *in*
(readers/unread current-in (readers/read-char *in*))
(skip-if-eol (if bind-in? current-in *in*))
input))))))
;; =============================================================================
;; CLJS Specifics
@@ -745,7 +749,7 @@
print println
caught repl-caught
reader #(readers/source-logging-push-back-reader
(PushbackReader. (io/reader *in*))
*in*
1 "NO_SOURCE_FILE")
print-no-newline print
source-map-inline true

0 comments on commit dfadee5

Please sign in to comment.