|
1346 | 1346 | else-tag #{else-tag})] |
1347 | 1347 | (into then-tag else-tag)))))))) |
1348 | 1348 |
|
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)] |
1355 | 1352 | 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))] |
1359 | 1358 | ret-tag |
1360 | 1359 | ANY_SYM))))) |
1361 | 1360 |
|
|
2101 | 2100 | ;; TODO: can we simplify - David |
2102 | 2101 | (merge be |
2103 | 2102 | {: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))) |
2104 | 2105 | :variadic? (:variadic? init-expr) |
2105 | 2106 | :max-fixed-arity (:max-fixed-arity init-expr) |
2106 | 2107 | :method-params (map :params (:methods init-expr))}) |
|
2267 | 2268 | (when (:field texpr) |
2268 | 2269 | texpr)))) |
2269 | 2270 | 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])))))) |
2270 | 2285 | (when-not texpr |
2271 | 2286 | (throw (error env "set! target must be a field or a symbol naming a var"))) |
2272 | 2287 | (cond |
|
3723 | 3738 | :meta meta-expr :expr expr :children [:meta :expr]}) |
3724 | 3739 | expr))) |
3725 | 3740 |
|
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))) |
3728 | 3749 | (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)) |
3732 | 3753 |
|
3733 | 3754 | (defn- repl-self-require? [env deps] |
3734 | 3755 | (and (:repl-env env) (some #{*cljs-ns*} deps))) |
|
4305 | 4326 | (when env/*compiler* |
4306 | 4327 | (:options @env/*compiler*)))) |
4307 | 4328 | ([forms opts] |
| 4329 | + (analyze-form-seq forms opts false)) |
| 4330 | + ([forms opts return-last?] |
4308 | 4331 | (let [env (assoc (empty-env) :build-options opts)] |
4309 | 4332 | (binding [*file-defs* nil |
4310 | 4333 | #?@(:clj [*unchecked-if* false |
4311 | 4334 | *unchecked-arrays* false]) |
4312 | 4335 | *cljs-ns* 'cljs.user |
4313 | 4336 | *cljs-file* nil |
4314 | 4337 | reader/*alias-map* (or reader/*alias-map* {})] |
4315 | | - (loop [ns nil forms forms] |
| 4338 | + (loop [ns nil forms forms last-ast nil] |
4316 | 4339 | (if (some? forms) |
4317 | 4340 | (let [form (first forms) |
4318 | 4341 | env (assoc env :ns (get-namespace *cljs-ns*)) |
4319 | 4342 | ast (analyze env form nil opts)] |
4320 | 4343 | (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))))))) |
4324 | 4349 |
|
4325 | 4350 | (defn ensure-defs |
4326 | 4351 | "Ensures that a non-nil defs map exists in the compiler state for a given |
|
0 commit comments