Skip to content

Commit 9a1fae9

Browse files
spinningtopsofdoomswannodette
authored andcommitted
CLJS-806: support ^:const
def now supports const making the var a constant (i.e. no redefining or setting). The emitted definition has the @const JSDoc tag added to it. Support for constants has been added to the case macro.
1 parent d551a4d commit 9a1fae9

File tree

3 files changed

+28
-5
lines changed

3 files changed

+28
-5
lines changed

src/clj/cljs/analyzer.clj

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -684,10 +684,13 @@
684684
tests (mapv #(mapv (fn [t] (analyze expr-env t)) %) tests)
685685
thens (mapv #(analyze env %) thens)
686686
default (analyze env default)]
687-
(assert (every? (fn [t] (and (= :constant (:op t))
688-
((some-fn number? string? char?) (:form t))))
687+
(assert (every? (fn [t]
688+
(or
689+
(-> t :info :const)
690+
(and (= :constant (:op t))
691+
((some-fn number? string? char?) (:form t)))))
689692
(apply concat tests))
690-
"case* tests must be numbers or strings")
693+
"case* tests must be numbers, strings, or constants")
691694
{:env env :op :case* :form form
692695
:v v :tests tests :thens thens :default default
693696
:children (vec (concat [v] tests thens (if default [default])))}))
@@ -783,6 +786,8 @@
783786
:var (symbol (str ns-name) (str sym))}))
784787
(when (namespace sym)
785788
(throw (error env "Can't def ns-qualified name")))
789+
(when (:const (resolve-var (dissoc env :locals) sym))
790+
(throw (error env "Can't redefine a constant")))
786791
(when-let [doc (:doc args)]
787792
(when-not (string? doc)
788793
(throw (error env "Too many arguments to def"))))
@@ -1178,6 +1183,8 @@
11781183

11791184
(symbol? target)
11801185
(do
1186+
(when (:const (resolve-var (dissoc env :locals) target))
1187+
(throw (error env "Can't set! a constant")))
11811188
(let [local (-> env :locals target)]
11821189
(when-not (or (nil? local)
11831190
(and (:field local)

src/clj/cljs/core.clj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1481,9 +1481,10 @@
14811481
(assoc-test m test expr env)))
14821482
{} (partition 2 clauses))
14831483
esym (gensym)
1484+
const? #(:const (and (list? %) (ana/resolve-var env (last %))))
14841485
tests (keys pairs)]
14851486
(cond
1486-
(every? (some-fn core/number? core/string? core/char?) tests)
1487+
(every? (some-fn core/number? core/string? core/char? const?) tests)
14871488
(core/let [no-default (if (odd? (count clauses)) (butlast clauses) clauses)
14881489
tests (mapv #(if (seq? %) (vec %) [%]) (take-nth 2 no-default))
14891490
thens (vec (take-nth 2 (drop 1 no-default)))]

test/clj/cljs/analyzer_tests.clj

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,19 @@
328328
(deftest test-cljs-1105
329329
;; munge turns - into _, must preserve the dash first
330330
(is (not= (a/gen-constant-id :test-kw)
331-
(a/gen-constant-id :test_kw))))
331+
(a/gen-constant-id :test_kw))))
332+
;; Constants
333+
334+
(deftest test-constants
335+
(is (.startsWith
336+
(try
337+
(a/analyze test-env '(do (def ^:const foo 123) (def foo 246)))
338+
(catch Exception e
339+
(.getMessage e)))
340+
"Can't redefine a constant"))
341+
(is (.startsWith
342+
(try
343+
(a/analyze test-env '(do (def ^:const foo 123) (set! foo 246)))
344+
(catch Exception e
345+
(.getMessage e)))
346+
"Can't set! a constant")))

0 commit comments

Comments
 (0)