Skip to content

Commit

Permalink
CLJS-801: str macro emits unoptimizable js code str macro now invokes…
Browse files Browse the repository at this point in the history
… the 1-arg version of str directly, does not create a js-array, and emits literals when possible (without a str call), all so that the closure compiler can optimize the generated js more agressively.
  • Loading branch information
favila authored and swannodette committed May 11, 2014
1 parent aa43866 commit c63db95
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 3 deletions.
27 changes: 24 additions & 3 deletions src/clj/cljs/core.clj
Expand Up @@ -201,10 +201,31 @@
(core/inc (core/quot c 32))))) (core/inc (core/quot c 32)))))


(defmacro str [& xs] (defmacro str [& xs]
(let [strs (->> (repeat (count xs) "cljs.core.str(~{})") ;; Eagerly stringify any string or char literals.
(interpose ",") (let [clean-xs (reduce (fn [acc x]
(core/cond
(core/or (core/string? x) (core/char? x))
(if (core/string? (peek acc))
(conj (pop acc) (core/str (peek acc) x))
(conj acc (core/str x)))
(core/nil? x) acc
:else (conj acc x)))
[] xs)
;; clean-xs now has no nils, chars, or string-adjoining-string. bools,
;; ints and floats will be emitted literally to allow JS string coersion.
strs (->> clean-xs
(map #(if (core/or (core/string? %) (core/integer? %)
(core/float? %) (core/true? %)
(core/false? %))
"~{}"
"cljs.core.str.cljs$core$IFn$_invoke$arity$1(~{})"))
(interpose "+")
(apply core/str))] (apply core/str))]
(list* 'js* (core/str "[" strs "].join('')") xs))) ;; Google closure advanced compile will stringify and concat strings and
;; numbers at compilation time.
(list* 'js* (core/str (if (core/string? (first clean-xs)) "(" "(''+")
strs ")")
clean-xs)))


(defn bool-expr [e] (defn bool-expr [e]
(vary-meta e assoc :tag 'boolean)) (vary-meta e assoc :tag 'boolean))
Expand Down
4 changes: 4 additions & 0 deletions test/cljs/cljs/core_test.cljs
Expand Up @@ -2212,5 +2212,9 @@
;; case keyword ;; case keyword
(assert (= (let [x "a"] (case x :a 1 "a")) "a")) (assert (= (let [x "a"] (case x :a 1 "a")) "a"))


;; CLJS-801
(assert (= "0atrue:key/wordsymb/olfalse[1 2 3 4]1234.56789"
(str 0 "a" true nil :key/word 'symb/ol false [1 2 3 4] 1234.5678 0x09)))

:ok :ok
) )

0 comments on commit c63db95

Please sign in to comment.