Skip to content

Commit 289014c

Browse files
committed
Merge branch 'cljs-2901'
2 parents b2f01f5 + dc18ed2 commit 289014c

4 files changed

Lines changed: 272 additions & 104 deletions

File tree

src/main/cljs/cljs/core.cljs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1817,7 +1817,7 @@ reduces them without incurring seq initialization"
18171817
(alength coll)
18181818

18191819
(string? coll)
1820-
(.-length coll)
1820+
^number (.-length coll)
18211821

18221822
(implements? ISeqable coll)
18231823
(accumulating-seq-count coll)

src/main/clojure/cljs/analyzer.cljc

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,16 +1346,15 @@
13461346
else-tag #{else-tag})]
13471347
(into then-tag else-tag))))))))
13481348

1349-
(defn infer-invoke [env e]
1350-
(let [{info :info :as f} (:fn e)]
1351-
(if-some [ret-tag (if (or (true? (:fn-var info))
1352-
(true? (:js-fn-var info)))
1353-
(:ret-tag info)
1354-
(when (= 'js (:ns info)) 'js))]
1349+
(defn infer-invoke [env {f :fn :keys [args] :as e}]
1350+
(let [me (assoc (find-matching-method f args) :op :fn-method)]
1351+
(if-some [ret-tag (infer-tag env me)]
13551352
ret-tag
1356-
(let [args (:args e)
1357-
me (assoc (find-matching-method f args) :op :fn-method)]
1358-
(if-some [ret-tag (infer-tag env me)]
1353+
(let [{:keys [info]} f]
1354+
(if-some [ret-tag (if (or (true? (:fn-var info))
1355+
(true? (:js-fn-var info)))
1356+
(:ret-tag info)
1357+
(when (= 'js (:ns info)) 'js))]
13591358
ret-tag
13601359
ANY_SYM)))))
13611360

@@ -2101,6 +2100,8 @@
21012100
;; TODO: can we simplify - David
21022101
(merge be
21032102
{:fn-var true
2103+
;; copy over the :fn-method information we need for invoke type inference
2104+
:methods (into [] (map #(select-keys % [:tag :fixed-arity :variadic?]) (:methods init-expr)))
21042105
:variadic? (:variadic? init-expr)
21052106
:max-fixed-arity (:max-fixed-arity init-expr)
21062107
:method-params (map :params (:methods init-expr))})
@@ -2267,6 +2268,20 @@
22672268
(when (:field texpr)
22682269
texpr))))
22692270
vexpr (analyze enve val)]
2271+
;; as top level fns are decomposed for Closure cross-module code motion, we need to
2272+
;; restore their :methods information
2273+
(when (seq? target)
2274+
(let [sym (some-> target second)
2275+
meta (meta sym)]
2276+
(when-let [info (and (= :fn (:op vexpr)) (:top-fn meta))]
2277+
(swap! env/*compiler* update-in
2278+
[::namespaces (-> env :ns :name) :defs sym :methods]
2279+
(fnil conj [])
2280+
;; just use original fn meta, as the fn method is already desugared
2281+
;; only get tag from analysis
2282+
(merge
2283+
(select-keys info [:fixed-arity :variadic?])
2284+
(select-keys (-> vexpr :methods first) [:tag]))))))
22702285
(when-not texpr
22712286
(throw (error env "set! target must be a field or a symbol naming a var")))
22722287
(cond
@@ -3723,12 +3738,18 @@
37233738
:meta meta-expr :expr expr :children [:meta :expr]})
37243739
expr)))
37253740

3726-
(defn infer-type [env ast _]
3727-
(if (nil? (:tag ast))
3741+
(defn infer-type [env {:keys [tag] :as ast} _]
3742+
(if (or (nil? tag) (= 'function tag))
3743+
;; infer-type won't get a chance to process :methods
3744+
;; so treat :fn as a special case for now, could probably
3745+
;; fix up to use :children to walk child nodes
3746+
(if (= :fn (:op ast))
3747+
(update ast :methods
3748+
(fn [ms] (into [] (map #(infer-type env % _)) ms)))
37283749
(if-some [tag (infer-tag env ast)]
3729-
(assoc ast :tag tag)
3730-
ast)
3731-
ast))
3750+
(assoc ast :tag tag)
3751+
ast))
3752+
ast))
37323753

37333754
(defn- repl-self-require? [env deps]
37343755
(and (:repl-env env) (some #{*cljs-ns*} deps)))
@@ -4305,22 +4326,26 @@
43054326
(when env/*compiler*
43064327
(:options @env/*compiler*))))
43074328
([forms opts]
4329+
(analyze-form-seq forms opts false))
4330+
([forms opts return-last?]
43084331
(let [env (assoc (empty-env) :build-options opts)]
43094332
(binding [*file-defs* nil
43104333
#?@(:clj [*unchecked-if* false
43114334
*unchecked-arrays* false])
43124335
*cljs-ns* 'cljs.user
43134336
*cljs-file* nil
43144337
reader/*alias-map* (or reader/*alias-map* {})]
4315-
(loop [ns nil forms forms]
4338+
(loop [ns nil forms forms last-ast nil]
43164339
(if (some? forms)
43174340
(let [form (first forms)
43184341
env (assoc env :ns (get-namespace *cljs-ns*))
43194342
ast (analyze env form nil opts)]
43204343
(if (= (:op ast) :ns)
4321-
(recur (:name ast) (next forms))
4322-
(recur ns (next forms))))
4323-
ns))))))
4344+
(recur (:name ast) (next forms) ast)
4345+
(recur ns (next forms) ast)))
4346+
(if return-last?
4347+
last-ast
4348+
ns)))))))
43244349

43254350
(defn ensure-defs
43264351
"Ensures that a non-nil defs map exists in the compiler state for a given

src/main/clojure/cljs/core.cljc

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3055,7 +3055,8 @@
30553055
`[(set! (. ~sym ~'-cljs$lang$maxFixedArity)
30563056
~(core/dec (count sig)))])
30573057
(js-inline-comment " @this {Function} ")
3058-
(set! (. ~sym ~'-cljs$lang$applyTo)
3058+
;; dissoc :top-fn so this helper gets ignored in cljs.analyzer/parse 'set!
3059+
(set! (. ~(vary-meta sym dissoc :top-fn) ~'-cljs$lang$applyTo)
30593060
~(apply-to)))))))
30603061

30613062
(core/defmacro copy-arguments [dest]
@@ -3080,23 +3081,26 @@
30803081
sig (remove '#{&} arglist)
30813082
c-1 (core/dec (count sig))
30823083
macro? (:macro meta)
3084+
mfa (core/cond-> c-1 macro? (core/- 2))
30833085
meta (assoc meta
30843086
:top-fn
30853087
{:variadic? true
3086-
:max-fixed-arity (core/cond-> c-1 macro? (core/- 2))
3088+
:fixed-arity mfa
3089+
:max-fixed-arity mfa
30873090
:method-params (core/cond-> [sig] macro? elide-implicit-macro-args)
30883091
:arglists (core/cond-> (core/list arglist) macro? elide-implicit-macro-args)
3089-
:arglists-meta (doall (map meta [arglist]))})]
3092+
:arglists-meta (doall (map meta [arglist]))})
3093+
name (with-meta name meta)]
30903094
`(do
3091-
(def ~(with-meta name meta)
3095+
(def ~name
30923096
(fn [~'var_args]
30933097
(let [args# (array)]
30943098
(copy-arguments args#)
30953099
(let [argseq# (when (< ~c-1 (alength args#))
30963100
(new ^::ana/no-resolve cljs.core/IndexedSeq
30973101
(.slice args# ~c-1) 0 nil))]
30983102
(. ~rname (~'cljs$core$IFn$_invoke$arity$variadic ~@(dest-args c-1) argseq#))))))
3099-
~(variadic-fn* rname method)
3103+
~(variadic-fn* name method)
31003104
~(core/when emit-var? `(var ~name))))))
31013105

31023106
(core/comment
@@ -3117,11 +3121,14 @@
31173121
(~(symbol
31183122
(core/str "cljs$core$IFn$_invoke$arity$" c))
31193123
~@(dest-args c)))]))
3120-
(fn-method [[sig & body :as method]]
3124+
(fn-method [name [sig & body :as method]]
31213125
(if (some '#{&} sig)
31223126
(variadic-fn* name method false)
3127+
;; fix up individual :fn-method meta for
3128+
;; cljs.analyzer/parse 'set! :top-fn handling
31233129
`(set!
3124-
(. ~name
3130+
(. ~(vary-meta name update :top-fn merge
3131+
{:variadic? false :fixed-arity (count sig)})
31253132
~(symbol (core/str "-cljs$core$IFn$_invoke$arity$"
31263133
(count sig))))
31273134
(fn ~method))))]
@@ -3135,19 +3142,22 @@
31353142
(map count sigs)
31363143
[(core/- (count (first (filter varsig? arglists))) 2)]))
31373144
macro? (:macro meta)
3145+
mfa (core/cond-> maxfa macro? (core/- 2))
31383146
meta (assoc meta
31393147
:top-fn
31403148
{:variadic? variadic
3141-
:max-fixed-arity (core/cond-> maxfa macro? (core/- 2))
3149+
:fixed-arity mfa
3150+
:max-fixed-arity mfa
31423151
:method-params (core/cond-> sigs macro? elide-implicit-macro-args)
31433152
:arglists (core/cond-> arglists macro? elide-implicit-macro-args)
31443153
:arglists-meta (doall (map meta arglists))})
31453154
args-sym (gensym "args")
3146-
param-counts (map count arglists)]
3155+
param-counts (map count arglists)
3156+
name (with-meta name meta)]
31473157
(core/when (not= (distinct param-counts) param-counts)
31483158
(ana/warning :overload-arity {} {:name name}))
31493159
`(do
3150-
(def ~(with-meta name meta)
3160+
(def ~name
31513161
(fn [~'var_args]
31523162
(case (alength (js-arguments))
31533163
~@(mapcat #(fixed-arity rname %) sigs)
@@ -3165,7 +3175,7 @@
31653175
(str "Invalid arity: " (- (alength (js-arguments)) 2))))
31663176
`(throw (js/Error.
31673177
(str "Invalid arity: " (alength (js-arguments))))))))))
3168-
~@(map fn-method fdecl)
3178+
~@(map #(fn-method name %) fdecl)
31693179
;; optimization properties
31703180
(set! (. ~name ~'-cljs$lang$maxFixedArity) ~maxfa)
31713181
~(core/when emit-var? `(var ~name))))))

0 commit comments

Comments
 (0)