Round 1 (correctness + dead code): - Fix duplicate java.util.HashMap registration in host-static.ss: the alist impl shadowed the hashtable ctor while leaving the hashtable methods bound, so .keySet/.values/.remove/.clear crashed. Drop the alist version. - Delete jolt-core/jolt/reader.clj: a 463-line dead duplicate reader, never required or compiled (the live reader is host/chez/reader.ss) and drifted. - Remove dead defs: ir/rt + :rt op + unused ir/op; the Janet branch in clojure.edn/drain-reader; a shadowed first clojure.string/trim-newline; io.ss jolt-char-array + the reader def-var (both shadowed by natives-array); concurrency.ss jolt-future-done?*; compile-eval.ss jolt-analyze-emit. Round 2 (perf + determinism): - emit-quoted-map-value / quoted sets now emit sorted by emitted text instead of host-hash order, which isn't stable across Chez versions (jolt-8479). - jolt-into folds through a transient, so into/vec/mapv/filterv onto a vector are O(n) instead of O(n^2). - deps resolve-deps walks its queue with an index cursor (was subvec-per-pop). - async channel and agent action queues use amortized-O(1) FIFOs; ArrayList is backed by a growable vector (O(1) add/get) instead of a list.
148 lines
3.3 KiB
Clojure
148 lines
3.3 KiB
Clojure
; Jolt Standard Library: clojure.string
|
|
; String manipulation functions using Jolt core string interop.
|
|
|
|
(defn blank?
|
|
[s]
|
|
(if (nil? s) true
|
|
(= 0 (count (str-trim s)))))
|
|
|
|
(defn capitalize
|
|
|
|
[s]
|
|
(if (< 1 (count s))
|
|
(str (str-upper (subs s 0 1))
|
|
(str-lower (subs s 1)))
|
|
(str-upper s)))
|
|
|
|
(defn lower-case
|
|
|
|
[s]
|
|
(str-lower s))
|
|
|
|
(defn upper-case
|
|
|
|
[s]
|
|
(str-upper s))
|
|
|
|
(defn includes?
|
|
|
|
[s substr]
|
|
(not (nil? (str-find substr s))))
|
|
|
|
(defn join
|
|
|
|
([coll] (str-join coll))
|
|
([separator coll] (str-join coll separator)))
|
|
|
|
(defn replace
|
|
[s match replacement]
|
|
(str-replace-all match replacement s))
|
|
|
|
(defn replace-first
|
|
[s match replacement]
|
|
(str-replace match replacement s))
|
|
|
|
(defn reverse
|
|
[s]
|
|
(str-reverse-b s))
|
|
|
|
(defn str-reverse
|
|
[s]
|
|
(str-reverse-b s))
|
|
|
|
(defn split
|
|
([s re] (split s re 0))
|
|
([s re limit]
|
|
;; Java Pattern.split semantics: limit > 0 caps the parts (trailing empties
|
|
;; kept); limit < 0 splits fully and keeps trailing empties; limit 0 (the
|
|
;; default) splits fully then drops trailing empty strings — but a no-match
|
|
;; result ([input], the only 1-element case) is returned as-is.
|
|
(let [parts (vec (str-split re s (if (pos? limit) limit nil)))]
|
|
(if (and (zero? limit) (> (count parts) 1))
|
|
(loop [v parts] (if (and (seq v) (= "" (peek v))) (recur (pop v)) v))
|
|
parts))))
|
|
|
|
(defn split-lines
|
|
"Split s on \\n or \\r\\n, returning a vector of lines."
|
|
[s]
|
|
(vec (str-split #"\r?\n" s)))
|
|
|
|
(defn starts-with?
|
|
|
|
[s substr]
|
|
(let [slen (count s) slen2 (count substr)]
|
|
(and (>= slen slen2)
|
|
(= (subs s 0 slen2) substr))))
|
|
|
|
(defn ends-with?
|
|
|
|
[s substr]
|
|
(let [slen (count s) slen2 (count substr)]
|
|
(and (>= slen slen2)
|
|
(= (subs s (- slen slen2)) substr))))
|
|
|
|
(defn trim
|
|
|
|
[s]
|
|
(str-trim s))
|
|
|
|
(defn triml
|
|
|
|
[s]
|
|
(str-triml s))
|
|
|
|
(defn trimr
|
|
|
|
[s]
|
|
(str-trimr s))
|
|
|
|
(defn escape
|
|
|
|
[s cmap]
|
|
(apply str
|
|
(map (fn [ch]
|
|
(if-let [rep (cmap ch)] rep (str ch)))
|
|
s)))
|
|
|
|
(defn index-of
|
|
"0-based index of the first occurrence of value in s, or nil."
|
|
([s value]
|
|
(str-find value s))
|
|
([s value from]
|
|
(let [idx (str-find value (subs s from))]
|
|
(when idx (+ from idx)))))
|
|
|
|
(defn last-index-of
|
|
|
|
([s value]
|
|
(let [r (str-reverse-b s) sval (str-reverse-b value)
|
|
idx (str-find sval r)]
|
|
(when idx (- (count s) (+ idx (count value))))))
|
|
([s value from]
|
|
(let [sub (subs s 0 from) r (str-reverse-b sub) sval (str-reverse-b value)
|
|
idx (str-find sval r)]
|
|
(when idx (- from (+ idx (count value)))))))
|
|
|
|
(defn re-quote-replacement
|
|
"Escape special characters (backslash and dollar) in a regex replacement
|
|
string so it is used literally rather than interpreted."
|
|
[replacement]
|
|
(apply str
|
|
(map (fn [ch]
|
|
(let [c (str ch)]
|
|
(if (or (= c "\\") (= c "$")) (str "\\" c) c)))
|
|
(seq replacement))))
|
|
|
|
;; Ported from clojure.string/trim-newline (CharSequence interop replaced with
|
|
;; portable count/subs). Removes all trailing \n or \r characters.
|
|
(defn trim-newline
|
|
"Removes all trailing newline \\n or return \\r characters from
|
|
string. Similar to Perl's chomp."
|
|
[s]
|
|
(loop [index (count s)]
|
|
(if (zero? index)
|
|
""
|
|
(let [c (subs s (dec index) index)]
|
|
(if (or (= c "\n") (= c "\r"))
|
|
(recur (dec index))
|
|
(subs s 0 index))))))
|