Skip to content

Commit beee96a

Browse files
Add read-all function (#986)
Emerged from #979 --------- Co-authored-by: Chris Rink <[email protected]>
1 parent 3677319 commit beee96a

File tree

3 files changed

+40
-39
lines changed

3 files changed

+40
-39
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
88
### Added
99
* Added the `CollReduce` and `KVReduce` protocols in `basilisp.core.protocols` and implemented `reduce` in terms of those protocols (#927)
1010
* Added `basilisp.pprint/print-table` function (#983)
11+
* Added `basilisp.core/read-all` function (#986)
1112

1213
### Changed
1314
* Improved on the nREPL server exception messages by matching that of the REPL user friendly format (#968)

src/basilisp/contrib/nrepl_server.lpy

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,6 @@
122122
[{:keys [client* code ns file _column _line] :as request} send-fn]
123123
(let [{:keys [*1 *2 *3 *e eval-ns]} @client*
124124
out-stream (StreamOutFn #(send-fn request {"out" %}))
125-
reader (io/StringIO code)
126125
ctx (basilisp.lang.compiler.CompilerContext. (or file "<nREPL Input>"))
127126
eval-ns (if ns
128127
(create-ns (symbol ns))
@@ -134,13 +133,11 @@
134133
*3 *3
135134
*e *e]
136135
(try
137-
(let [results (for [form (seq (basilisp.lang.reader/read reader
138-
*resolver*
139-
*data-readers*))]
136+
(let [result (last
137+
(for [form (read-all (io/StringIO code))]
140138
(basilisp.lang.compiler/compile-and-exec-form form
141139
ctx
142-
*ns*))
143-
result (last results)]
140+
*ns*)))]
144141
(send-value request send-fn [result {:ns (str *ns*)}]))
145142
(catch python/Exception e
146143
(debug :eval-exception e)
@@ -183,9 +180,7 @@
183180
[resolve-ns symbol-str]
184181
(let [reader (io/StringIO symbol-str)
185182
{:keys [form error]} (try {:form (binding [*ns* resolve-ns]
186-
(first (seq (basilisp.lang.reader/read reader
187-
*resolver*
188-
*data-readers*))))}
183+
(read reader))}
189184
(catch python/Exception e
190185
(debug :symbol-identify-reader-error :input symbol-str :exception e)
191186
{:error (str e)}))]

src/basilisp/core.lpy

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4428,6 +4428,17 @@
44284428
*resolver*
44294429
basilisp.lang.runtime/resolve-alias)
44304430

4431+
(defn- read-iterator
4432+
[opts x]
4433+
(let [read (:read opts basilisp.lang.reader/read)]
4434+
(read x
4435+
*resolver*
4436+
*data-readers*
4437+
(:eof opts)
4438+
(= (:eof opts) :eofthrow)
4439+
(:features opts)
4440+
(not= :preserve (:read-cond opts)))))
4441+
44314442
(defn read-string
44324443
"Read a string of Basilisp code.
44334444

@@ -4440,17 +4451,7 @@
44404451
([s]
44414452
(read-string {:eof :eofthrow} s))
44424453
([opts s]
4443-
(first (basilisp.lang.reader/read-str s
4444-
*resolver*
4445-
*data-readers*
4446-
(:eof opts)
4447-
(if (= (:eof opts) :eofthrow)
4448-
true
4449-
false)
4450-
(:features opts)
4451-
(if (= :preserve (:read-cond opts))
4452-
false
4453-
true)))))
4454+
(first (read-iterator (assoc opts :read basilisp.lang.reader/read-str) s))))
44544455

44554456
(defn read
44564457
"Read the next form from the ``stream``\\. If no stream is specified, uses the value
@@ -4468,23 +4469,29 @@
44684469
([stream]
44694470
(read stream true nil))
44704471
([opts stream]
4471-
(first (basilisp.lang.reader/read stream
4472-
*resolver*
4473-
*data-readers*
4474-
(:eof opts)
4475-
(if (= (:eof opts) :eofthrow)
4476-
true
4477-
false)
4478-
(:features opts)
4479-
(if (= :preserve (:read-cond opts))
4480-
false
4481-
true))))
4472+
(first (read-iterator opts stream)))
44824473
([stream eof-error? eof-value]
4483-
(first (basilisp.lang.reader/read stream
4484-
*resolver*
4485-
*data-readers*
4486-
eof-value
4487-
eof-error?))))
4474+
(first (read-iterator {:eof (if eof-error? :eofthrow eof-value)} stream))))
4475+
4476+
(defn read-all
4477+
"Eagerly read all forms from the ``stream``\\. If no stream is specified, uses the
4478+
value currently bound to :lpy:var:`*in*`.
4479+
4480+
Callers may bind a map of readers to :lpy:var:`*data-readers*` to customize
4481+
the data readers used reading this string
4482+
4483+
The stream must satisfy the interface of :external:py:class:`io.TextIOBase`\\, but
4484+
does not require any pushback capabilities. The default
4485+
``basilisp.lang.reader.StreamReader`` can wrap any object implementing ``TextIOBase``
4486+
and provide pushback capabilities."
4487+
([stream]
4488+
(read-all nil stream))
4489+
([opts stream]
4490+
(let [eof (python/object)]
4491+
(->> (read-iterator (assoc opts :eof eof) stream)
4492+
seq
4493+
(take-while #(not (identical? % eof)))
4494+
doall))))
44884495

44894496
(defn eval
44904497
"Evaluate a form (not a string) and return its result.
@@ -4517,9 +4524,7 @@
45174524
(python/str))
45184525
ctx (basilisp.lang.compiler.CompilerContext. (or src "<Load Input>"))]
45194526
(last
4520-
(for [form (seq (basilisp.lang.reader/read reader
4521-
*resolver*
4522-
*data-readers*))]
4527+
(for [form (seq (read-all reader))]
45234528
(basilisp.lang.compiler/compile-and-exec-form form
45244529
ctx
45254530
*ns*)))))

0 commit comments

Comments
 (0)