├── script
├── repl
└── test
├── images
└── part-of-typed-clojure-project.png
├── src
├── test
│ ├── cljs
│ │ └── cljs
│ │ │ └── core
│ │ │ └── typed
│ │ │ └── test
│ │ │ ├── dep_one.cljs
│ │ │ ├── ann.cljs
│ │ │ ├── dep_two.cljs
│ │ │ ├── goog_import.cljs
│ │ │ ├── identity.cljs
│ │ │ ├── js_obj.cljs
│ │ │ ├── dnolen
│ │ │ └── utils
│ │ │ │ ├── helpers.cljs
│ │ │ │ ├── dom.cljs
│ │ │ │ └── reactive.cljs
│ │ │ ├── csp.cljs
│ │ │ └── ympbyc
│ │ │ └── test_base_env.cljs
│ └── clojure
│ │ └── clojure
│ │ └── core
│ │ └── typed
│ │ └── test
│ │ ├── cljs_utils.clj
│ │ ├── cljs_core.clj
│ │ └── cljs.clj
├── assembly
│ └── slim.xml
└── main
│ └── clojure
│ └── clojure
│ └── core
│ └── typed
│ ├── check_ns_cljs.clj
│ ├── analyzer_api_intercept.clj
│ ├── bootstrap_cljs.clj
│ ├── check_form_cljs.clj
│ ├── util_cljs.clj
│ ├── check
│ └── dot_cljs.clj
│ ├── emit_form_cljs.clj
│ ├── analyze_cljs.clj
│ ├── jsnominal_env.clj
│ ├── base_env_helper_cljs.clj
│ ├── check_cljs.clj
│ └── base_env_cljs.clj
├── IDEAS
├── README.md
├── deps.edn
├── TODO
├── pom.xml
└── epl-v10.html
/script/repl:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | clj -Atest:nREPL
4 |
--------------------------------------------------------------------------------
/script/test:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | clojure -Atest:runner
4 |
--------------------------------------------------------------------------------
/images/part-of-typed-clojure-project.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/clojure/core.typed.checker.js/master/images/part-of-typed-clojure-project.png
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/dep_one.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.dep-one
2 | (:require [cljs.core.typed :as t :include-macros true]))
3 |
4 | (def a 1)
5 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/ann.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.ann
2 | (:require [cljs.core.typed :refer-macros [ann check-ns]]))
3 |
4 | (ann foo number)
5 | (def foo 1)
6 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/dep_two.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.dep-two
2 | (:require [cljs.core.typed :as t :include-macros true]
3 | [cljs.core.typed.test.dep-one :as one]))
4 |
5 | (def b (inc one/a))
6 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/goog_import.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.goog-import
2 | (:require [cljs.core.typed :as t])
3 | (:import [goog.events EventType]))
4 |
5 | (t/ann et [EventType -> EventType])
6 | (defn et [e]
7 | e)
8 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/identity.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.identity
2 | (:require [cljs.core.typed :as t]))
3 |
4 | (t/ann my-identity (t/All [x] [x -> (t/U x t/Number)]))
5 | (defn my-identity [x]
6 | (if (number? x)
7 | (inc x)
8 | x))
9 |
--------------------------------------------------------------------------------
/IDEAS:
--------------------------------------------------------------------------------
1 | 1. Generate TS annotations using https://github.com/fable-compiler/ts2fable
2 | 2. Generate Google Closure annotations using https://github.com/jleyba/js-dossier
3 |
4 | Converting TS->Goog
5 | - https://github.com/honzabrecka/ts-to-goog
6 | - https://github.com/angular/tsickle
7 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/js_obj.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.js-obj
2 | (:require [cljs.core.typed :as t]))
3 |
4 | (t/ann jo [-> (t/JSObj {:a t/JSNumber})])
5 | (defn jo []
6 | #js {:a 2})
7 |
8 | #_
9 | (t/ann jo2 [-> (t/JSObj {:a t/JSNumber})])
10 | ;; TODO
11 | #_
12 | (defn jo2 []
13 | (js-obj :a 2))
14 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/dnolen/utils/helpers.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.dnolen.utils.helpers)
2 |
3 | (defn ^{:ann '[Any Any -> Any]}
4 | index-of [xs x]
5 | (let [len (count xs)]
6 | (loop [i 0]
7 | (if (< i len)
8 | (if (= (nth xs i) x)
9 | i
10 | (recur (inc i)))
11 | -1))))
12 |
--------------------------------------------------------------------------------
/src/assembly/slim.xml:
--------------------------------------------------------------------------------
1 |
2 | slim
3 |
4 | jar
5 |
6 | false
7 |
8 |
9 | src/main/clojure
10 | /
11 |
12 |
13 | src/main/cljs
14 | /
15 |
16 |
17 | src/main/java
18 | /
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # core.typed.checker.js
2 |
3 |
4 |
5 | Type checker for Typed Clojure, for ClojureScript on JS.
6 |
7 | ## YourKit
8 |
9 | YourKit is kindly supporting core.typed and other open source projects with its full-featured Java Profiler.
10 | YourKit, LLC is the creator of innovative and intelligent tools for profiling
11 | Java and .NET applications. Take a look at YourKit's leading software products:
12 |
13 | * YourKit Java Profiler and
14 | * YourKit .NET Profiler.
15 |
16 | ## License
17 |
18 | Copyright © Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
19 |
20 | Licensed under the EPL (see the file epl-v10.html).
21 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/check_ns_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.check-ns-cljs
10 | (:require [cljs.compiler :as comp]
11 | [clojure.core.typed.current-impl :as impl]
12 | [cljs.env :as env]
13 | [clojure.core.typed.util-cljs :as ucljs]
14 | [clojure.core.typed.check-ns-common :as chk-ns]))
15 |
16 | (defn check-ns-info
17 | [ns-or-syms opt]
18 | (ucljs/with-cljs-typed-env
19 | (comp/with-core-cljs
20 | nil
21 | #(chk-ns/check-ns-info impl/clojurescript ns-or-syms opt))))
22 |
23 | (defn check-ns
24 | [ns-or-syms opt]
25 | (ucljs/with-cljs-typed-env
26 | (comp/with-core-cljs
27 | nil
28 | #(chk-ns/check-ns impl/clojurescript ns-or-syms opt))))
29 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/analyzer_api_intercept.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.analyzer-api-intercept
10 | (:require [cljs.analyzer.api :as api]
11 | [clojure.core.typed.ast-utils :as ast-u]))
12 |
13 | (def ops-found (atom #{}))
14 |
15 | (defn reset-found []
16 | (reset! ops-found #{}))
17 |
18 | (defn walk-collect-ops [{:keys [op children] :as node}]
19 | (when-not (some (partial = op) @ops-found)
20 | (swap! ops-found #(conj % op)))
21 | (when children
22 | (doseq [c children]
23 | (walk-collect-ops (c node)))))
24 |
25 | (defn analyze
26 | ([env form] (analyze env form nil {}))
27 | ([env form x opts]
28 | (let [result (api/analyze env form x opts)]
29 | (walk-collect-ops result)
30 | ;(println ops-found)
31 | result)))
32 |
33 | (defn empty-env []
34 | (api/empty-env))
35 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/csp.cljs:
--------------------------------------------------------------------------------
1 | ; from David Nolen's blog
2 | (ns cljs.core.typed.test.csp
3 | (:refer-clojure :exclude [map])
4 | (:require [cljs.core.async :as async
5 | :refer [! chan put! timeout]]
6 | [clojure.string :as string]
7 | [cljs.core.typed.test.dnolen.utils.dom :refer [by-id set-html! offset]]
8 | [cljs.core.typed.test.dnolen.utils.reactive :refer [listen map]])
9 | (:require-macros [cljs.core.async.macros :refer [go alt!]]))
10 |
11 | (def c (chan))
12 |
13 | (defn render [q]
14 | (apply str
15 | (for [p (reverse q)]
16 | (str "
Process " p "
"))))
17 |
18 | #_(go (while true (! c 1)))
19 | #_(go (while true (! c 2)))
20 | #_(go (while true (! c 3)))
21 |
22 | (defn peekn
23 | "Returns vector of (up to) n items from the end of vector v"
24 | [v n]
25 | (if (> (count v) n)
26 | (subvec v (- (count v) n))
27 | v))
28 |
29 | (let [el (by-id "ex0")
30 | out (by-id "ex0-out")]
31 | (go (loop [q []]
32 | (set-html! out (render q))
33 | (recur (-> (conj q ( (t/U nil js/HTMLElement)])
9 | (defn by-id [id]
10 | (.getElementById js/document id))
11 |
12 | (ann set-html! [js/HTMLElement t/JSString -> t/JSString])
13 | (defn set-html! [el s]
14 | (set! (.-innerHTML el) s))
15 |
16 | (ann set-text! [js/Element (t/U t/JSString t/JSNumber) -> js/Window])
17 | (defn set-text! [el s]
18 | (dom/setTextContent el s))
19 |
20 | (ann set-class! [(t/U js/Node nil) t/JSString -> t/Any])
21 | (defn set-class! [el name]
22 | (classes/set el name))
23 |
24 | (ann add-class! [(t/U nil js/Node) t/JSString -> t/JSBoolean])
25 | (defn add-class! [el name]
26 | (classes/add el name))
27 |
28 | (ann remove-class! [(t/U js/Node nil) (t/U nil t/JSString) -> t/JSBoolean])
29 | (defn remove-class! [el name]
30 | (classes/remove el name))
31 |
32 | (ann tag-match [t/JSString -> [js/HTMLElement -> t/Any]])
33 | (defn tag-match [tag]
34 | (fn [el]
35 | (when-let [tag-name (.-tagName el)]
36 | (t/ann-form tag-name t/JSString)
37 | (= tag (.toLowerCase tag-name)))))
38 |
39 | (ann el-matcher [t/Any -> [t/Any -> t/Any]])
40 | (defn el-matcher [el]
41 | (fn [other] (identical? other el)))
42 |
43 | (ann by-tag-name [(t/U nil js/Document js/Element) (t/U nil t/JSString)
44 | -> (t/U nil (ISeq js/Element))])
45 | (defn by-tag-name [el tag]
46 | (prim-seq (dom/getElementsByTagNameAndClass tag nil el)))
47 |
48 | (ann offset [(t/U nil js/Element) -> '[t/JSNumber t/JSNumber]])
49 | (defn offset [el]
50 | [(style/getPageOffsetLeft el) (style/getPageOffsetTop el)])
51 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/check_form_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.check-form-cljs
10 | (:require [clojure.core.typed.check-form-common :as chk-form]
11 | [clojure.core.typed.analyze-cljs :as ana-cljs]
12 | [clojure.core.typed.check-cljs :as chk-cljs]
13 | [clojure.core.typed.util-cljs :as ucljs]
14 | [cljs.env :as env]
15 | [cljs.compiler :as comp]
16 | [clojure.core.typed.current-impl :as impl]))
17 |
18 | (defn config-map []
19 | {:impl impl/clojurescript
20 | :unparse-ns (ucljs/cljs-ns)
21 | :ast-for-form ana-cljs/ast-for-form
22 | :check-expr chk-cljs/check-expr})
23 |
24 | (defn check-form-info
25 | [form & opt]
26 | (let [config (config-map)]
27 | (impl/with-full-impl (:impl config)
28 | (apply chk-form/check-form-info config
29 | form opt))))
30 |
31 | (defn check-form-cljs
32 | "Check a single form with an optional expected type.
33 | Intended to be called from Clojure. For evaluation at the Clojurescript
34 | REPL see cf."
35 | [form expected expected-provided?]
36 | (ucljs/with-cljs-typed-env
37 | (comp/with-core-cljs
38 | nil
39 | #(let [config (config-map)]
40 | (impl/with-full-impl (:impl config)
41 | (chk-form/check-form* config
42 | form expected expected-provided?))))))
43 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/util_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns ^:skip-wiki clojure.core.typed.util-cljs
10 | (:require [clojure.core.typed.current-impl :as impl]
11 | [cljs.analyzer :as ana]
12 | [clojure.core.typed.emit-form-cljs :as emit-form]
13 | [cljs.compiler :as comp]
14 | [cljs.env :as env]))
15 |
16 | (def default-env (env/default-compiler-env))
17 |
18 | (defmacro with-cljs-typed-env [& body]
19 | `(env/with-compiler-env (or env/*compiler* default-env)
20 | ~@body))
21 |
22 | (defn var-exists? [env prefix suffix]
23 | (let [compiler env/*compiler*
24 | _ (assert compiler)]
25 | (contains? (get-in @compiler [::ana/namespaces prefix :defs])
26 | suffix)))
27 |
28 | (defn resolve-var [nsym sym]
29 | {:post [((some-fn symbol? nil?) %)]}
30 | (let [unresolved? (atom false)
31 | r (with-cljs-typed-env
32 | (binding [ana/*cljs-ns* nsym]
33 | (comp/with-core-cljs
34 | nil
35 | #(ana/resolve-var (ana/empty-env) sym
36 | (fn [env ns sym]
37 | (when-not (var-exists? env ns sym)
38 | (reset! unresolved? true)))))))
39 | sym* (when-not @unresolved?
40 | (:name r))
41 | _ (when sym*
42 | (assert (symbol? sym*) sym*)
43 | (assert (namespace sym*) sym*))]
44 | ;(prn sym sym*)
45 | sym*))
46 |
47 | (defn cljs-ns []
48 | ana/*cljs-ns*)
49 |
50 | (defn emit-form [ast]
51 | (emit-form/emit-form ast))
52 |
53 | (defmacro with-core-cljs-typed [& body]
54 | `(comp/with-core-cljs
55 | nil
56 | #(do (when-not (get-in @env/*compiler* [::ana/namespaces 'cljs.core.typed :defs])
57 | (ana/analyze-file "cljs/core/typed.cljs"))
58 | ~@body)))
59 |
--------------------------------------------------------------------------------
/deps.edn:
--------------------------------------------------------------------------------
1 | {:paths ["src/main/clojure"
2 | "src/main/cljs"
3 | ]
4 | :deps {org.clojure/clojure {:mvn/version "1.10.0-beta5"}
5 | org.clojure/core.typed {:local/root "../module-check"}
6 | org.clojure/core.typed.rt {:local/root "../module-rt"}
7 | org.clojure/clojurescript {:mvn/version "1.10.373"}}
8 | :aliases {:nREPL
9 | {:extra-paths ["script"]
10 | :extra-deps
11 | {nrepl/nrepl {:mvn/version "0.4.5"}
12 | cider/piggieback {:mvn/version "0.3.8"}}
13 | :main-opts ["-m" "nrepl.cmdline"
14 | "--interactive"]}
15 |
16 | :reply
17 | {:extra-deps
18 | {reply {:mvn/version "0.4.1"}}
19 | :main-opts ["-m" "reply.main"]}
20 |
21 | :start-repl
22 | {:extra-paths ["script"]
23 | :extra-deps
24 | {com.bhauman/rebel-readline {:mvn/version "0.1.4"}}
25 | :main-opts ["-m" "start-repl"]}
26 |
27 | :clj-1.10.0-beta5 {:override-deps {org.clojure/clojure {:mvn/version "1.10.0-beta5"}}}
28 | :test
29 | {:extra-paths ["src/test/clojure"
30 | "src/test/cljs"
31 | "../module-check/src/test/clojure"
32 | "../module-check/src/test/cljs"]
33 | :extra-deps {org.clojure/tools.nrepl {:mvn/version "0.2.6"
34 | :exclusions [org.clojure/clojure]}
35 | org.clojure/core.async {:mvn/version "0.3.465"
36 | :exclusions [org.clojure/tools.analyzer.jvm]}
37 | org.clojure/tools.trace {:mvn/version "0.7.5"
38 | :exclusions [org.clojure/clojure]}
39 | org.clojure/test.check {:mvn/version "0.9.0"}
40 | com.gfredericks/test.chuck {:mvn/version "0.2.6"}}}
41 | :runner
42 | {:extra-deps {org.typedclojure/test-runner
43 | {:git/url "https://github.com/typedclojure/test-runner"
44 | :sha "2d7af465ac90b2d083753daf251bdb4a09ae97cd"}}
45 | :main-opts ["-m" "cognitect.test-runner"
46 | "-d" "src/test/clojure/clojure/core/typed/test"
47 | "-r" ".*"
48 | ;"-w" "clojure.test.junit/with-junit-output"
49 | ;"-o" "junit-output.xml"
50 | ]}}}
51 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/check/dot_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.check.dot-cljs
10 | (:require [clojure.core.typed.type-rep :as r]
11 | [clojure.core.typed.utils :as u]
12 | [clojure.core.typed.type-ctors :as c]
13 | [clojure.core.typed.jsnominal-env :as jsnom]
14 | [clojure.core.typed.parse-unparse :as prs]
15 | [clojure.core.typed.check.funapp :as funapp]
16 | [clojure.core.typed.errors :as err]))
17 |
18 | (defn check-dot [check {:keys [target field method args] :as dot-expr} expected]
19 | (let [ctarget (check target)
20 | target-t (-> ctarget u/expr-type r/ret-t)
21 | resolved (let [t (c/fully-resolve-type target-t)]
22 | ;TODO DataType
23 | (when ((some-fn r/JSNominal?
24 | r/JSString?
25 | #_r/DataType?) t)
26 | t))]
27 | (if resolved
28 | (cond
29 | field
30 | (let [field-type (cond
31 | (r/JSString? resolved)
32 | (jsnom/get-field 'string nil field)
33 | (r/JSNominal? resolved)
34 | (jsnom/get-field (:name resolved) (:poly? resolved) field))
35 | _ (assert field-type (str "Don't know how to get field " field
36 | " from " (prs/unparse-type resolved)))]
37 | (assoc dot-expr
38 | u/expr-type (r/ret field-type)))
39 | :else
40 | (let [method-type (cond
41 | (r/JSString? resolved)
42 | (jsnom/get-method 'string nil method)
43 | (r/JSNominal? resolved)
44 | (jsnom/get-method (:name resolved) (:poly? resolved) method))
45 | _ (assert method-type (str "Don't know how to call method " method
46 | " from " (prs/unparse-type resolved)))
47 | cargs (mapv check args)
48 | actual (funapp/check-funapp nil cargs (r/ret method-type) (map u/expr-type cargs)
49 | expected)]
50 | (assoc dot-expr
51 | u/expr-type actual)))
52 | (err/tc-delayed-error (str "Don't know how to use type " (prs/unparse-type target-t)
53 | " with "
54 | (if field (str "field " field)
55 | (str "method " method)))
56 | :return
57 | (assoc dot-expr
58 | u/expr-type (r/ret (or (when expected
59 | (r/ret-t expected))
60 | (r/TCError-maker))))))))
61 |
--------------------------------------------------------------------------------
/TODO:
--------------------------------------------------------------------------------
1 | * Next
2 |
3 | [ ] add JS primitives
4 | [x] cljs.core.typed/JSUndefined
5 | * 'undefined' in TypeScript
6 | * idea 1: nil expands to (U nil Undefined) internally, but always elide Undefined
7 | when pretty-printing a union that includes both nil and Undefined.
8 | * This to avoids:
9 | Expected: nil, Given: nil
10 | since
11 | Expected: (U Undefined nil), Given: nil
12 | * Problem: lots of special casing for Nil? in the type checker
13 | * support nil?/undefined?/some? predicates
14 | * recognize undefined as a false value
15 | * (= x nil) ;=> (is x (U nil Undefined))
16 | * idea 2: New type JSNull
17 | (U JSNull JSUndefined) <: nil
18 | nil Any])
28 | (f nil)
29 | * structural equality on `nil` should be enhanced
30 | (let [x :- JSNull nil
31 | y :- nil nil
32 | z :- JSUndefined ...]
33 | (= x y z))
34 | ; true ; tt | ff
35 | [x] support undefined? predicates
36 | * unit tests for 'if'
37 | [*] cljs.core.typed/JSNumber
38 | * 'number' in TypeScript
39 | * (ann number? (Pred JSNumber))
40 | [*] cljs.core.typed/JSBoolean
41 | * 'boolean' in TypeScript
42 | [*] cljs.core.typed/JSString
43 | * 'string' in TypeScript
44 | [*] cljs.core.typed/JSSymbol
45 | * 'symbol' in TypeScript
46 | [*] add cljs.core.typed/JSObject
47 | * any non-primitive type
48 | * 'object' in TypeScript
49 | * https://blog.mariusschulz.com/2017/02/24/typescript-2-2-the-object-type
50 | * 'Object' in Google Closure (or 'Object,?>' maybe?)
51 | * https://github.com/google/closure-compiler/wiki/A-word-about-the-type-Object
52 | [*] rename int => cljs.core.typed/JSInteger
53 | * for `integer?`
54 | [ ] create JSObj type
55 | * analogous to HMap
56 | * Use undefined to signal optional
57 | * (JSObj {:a (t/U Node t/JSUndefined)
58 | :b})
59 | [ ] implement ann-js
60 | [ ] implement ann-jsclass
61 | [ ] implement ann-jsinterface
62 | [ ] implement ann-jsalias
63 | [ ] support js/undefined top-level builtin classes
64 | * eg. js/String, js/Symbol, js/Function
65 | * Note. js/Object is 'Object' in TypeScript
66 | * Note. js/Function is 'Function' in Google Closure
67 | * Note. js/Array is 'Array' in Google Closure
68 | * https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects
69 | * https://funcool.github.io/clojurescript-unraveled/
70 | [ ] add common Regex annotation for #""
71 | [ ] remove cljs.core.typed/IPersistentMap etc.
72 | [ ] remove ArrayCLJS
73 | * replace with js/Array
74 | [ ] remove FunctionCLJS
75 | * replace with js/Function
76 | [ ] fix cct.subtype/resolve-JS-reference function
77 | [ ] remove letfn> etc.
78 | * replace with non-> versions
79 | * rename primitives to lower case (or namespaced in `js`?)
80 | * JSboolean, JSsymbol, JSstring, JSnull, JSundefined
81 | * js/boolean, js/symbol, js/string, js/null, js/undefined
82 | * handle special Closure types
83 | * possibly prefix with `js`?
84 | * js/IObject, js/IArrayLike, js/IThenable
85 |
86 | # Later
87 |
88 | * add heterogeneous object type
89 | * optional entries
90 | * delete Array stuff for CLJ/CLJS
91 | * revise default js-nominal mappings
92 | * pprint JSUndefined and JSNull to `nil` when appropriate
93 | * `boolean?` tests for primitive boolean
94 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/emit_form_cljs.clj:
--------------------------------------------------------------------------------
1 | ; Copyright (c) Rich Hickey. All rights reserved.
2 | ; The use and distribution terms for this software are covered by the
3 | ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ; which can be found in the file epl-v10.html at the root of this distribution.
5 | ; By using this software in any fashion, you are agreeing to be bound by
6 | ; the terms of this license.
7 | ; You must not remove this notice, or any other, from this software.
8 |
9 | ;copied from clojure.tools.analyzer.passes.js.emit-form
10 | (ns ^:skip-wiki clojure.core.typed.emit-form-cljs
11 | (:require [clojure.tools.analyzer.passes
12 | [emit-form :as default]
13 | [uniquify :refer [uniquify-locals]]]
14 | [clojure.string :as s]
15 | [cljs.tagged-literals :refer [->JSValue]])
16 | (:import cljs.tagged_literals.JSValue
17 | java.io.Writer))
18 |
19 | (defmulti -emit-form (fn [{:keys [op]} _] op))
20 |
21 | (defn -emit-form*
22 | [{:keys [form] :as ast} opts]
23 | (let [expr (-emit-form ast opts)]
24 | (if-let [m (and (instance? clojure.lang.IObj expr)
25 | (meta form))]
26 | (with-meta expr (merge m (meta expr)))
27 | expr)))
28 |
29 | (defn emit-form
30 | "Return the form represented by the given AST
31 | Opts is a set of options, valid options are:
32 | * :hygienic
33 | * :qualified-symbols"
34 | {:pass-info {:walk :none :depends #{#'uniquify-locals} :compiler true}}
35 | ([ast] (emit-form ast #{}))
36 | ([ast opts]
37 | (binding [default/-emit-form* -emit-form*]
38 | (-emit-form* ast opts))))
39 |
40 | (defn emit-hygienic-form
41 | "Return an hygienic form represented by the given AST"
42 | {:pass-info {:walk :none :depends #{#'uniquify-locals} :compiler true}}
43 | [ast]
44 | (binding [default/-emit-form* -emit-form*]
45 | (-emit-form* ast #{:hygienic})))
46 |
47 | (defmethod -emit-form :default
48 | [ast opts]
49 | (default/-emit-form ast opts))
50 |
51 | (defmethod -emit-form :js
52 | [{:keys [segs args]} opts]
53 | (list* 'js* (s/join "~{}" segs) (mapv #(-emit-form* % opts) args)))
54 |
55 | (defmethod -emit-form :js-object
56 | [{:keys [keys vals]} opts]
57 | (->JSValue (zipmap keys (map #(-emit-form* % opts) vals))))
58 |
59 | (defmethod -emit-form :js-array
60 | [{:keys [items]} opts]
61 | (->JSValue (mapv #(-emit-form* % opts) items)))
62 |
63 | (defmethod print-method JSValue [^JSValue o ^Writer w]
64 | (.write w "#js ")
65 | (.write w (str (.val o))))
66 |
67 | (defmethod -emit-form :deftype
68 | [{name :t :keys [fields pmask body]} opts]
69 | (list 'deftype* name (map #(-emit-form* % opts) fields) pmask
70 | (-emit-form* body opts)))
71 |
72 | (defmethod -emit-form :defrecord
73 | [{name :t :keys [fields pmask body]} opts]
74 | (list 'defrecord* name (map #(-emit-form* % opts) fields) pmask
75 | (-emit-form* body opts)))
76 |
77 | (defmethod -emit-form :case-then
78 | [{:keys [then]} opts]
79 | (-emit-form* then opts))
80 |
81 | (defmethod -emit-form :case-test
82 | [{:keys [test]} opts]
83 | (-emit-form* test opts))
84 |
85 | (defmethod -emit-form :case
86 | [{:keys [test nodes default]} opts]
87 | `(case* ~(-emit-form* test opts)
88 | ~@(reduce (fn [acc {:keys [tests then]}]
89 | (-> acc
90 | (update-in [0] conj (mapv #(-emit-form* % opts) tests))
91 | (update-in [1] conj (-emit-form* then opts))))
92 | [[] []] nodes)
93 | ~(-emit-form* default opts)))
94 |
95 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/core/typed/test/cljs_utils.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.core.typed.test.cljs-utils
2 | (:require [clojure.core.typed :as clj-t]
3 | [cljs.core.typed :as cljs-t]
4 | [cljs.repl.rhino :as rhino]
5 | [cljs.repl :as repl]
6 | [cljs.analyzer :as ana]
7 | [clojure.core.typed.analyze-cljs :as ana-cljs]
8 | [clojure.core.typed.errors :as err]
9 | [clojure.set :as set]))
10 |
11 | (cljs-t/load-if-needed)
12 |
13 | (require '[clojure.test :refer :all :as test]
14 | '[cljs.core.typed :as t]
15 | '[clojure.core.typed.type-ctors :as c]
16 | '[clojure.core.typed.type-rep :as r]
17 | '[clojure.core.typed.current-impl :as impl]
18 | '[clojure.core.typed.parse-unparse :as prs]
19 | '[clojure.core.typed.subtype :as sub]
20 | '[clojure.core.typed.util-cljs :as ucljs]
21 | '[clojure.core.typed.coerce-utils :as coerce]
22 | '[clojure.core.typed.test.common-utils :as common-test]
23 | '[clojure.core.typed.check-form-cljs :as chk-frm-cljs]
24 | '[cljs.env :as env])
25 |
26 | (defmacro cljs [& body]
27 | `(impl/with-cljs-impl
28 | (ucljs/with-cljs-typed-env
29 | ~@body)))
30 |
31 | (defmacro is-cljs [& body]
32 | `(is (cljs ~@body)))
33 |
34 | (defmacro is-cf [& body]
35 | `(is-cljs (t/cf ~@body) true))
36 |
37 | (defn check-opt [opt]
38 | #_(assert (empty? (set/difference (set (keys opt))
39 | #{:expected :ret}))))
40 |
41 | (defn tc-common* [frm {{:keys [syn provided?]} :expected-syntax :keys [expected-ret] :as opt}]
42 | (let [nsym (gensym 'clojure.core.typed.test.temp)]
43 | (check-opt opt)
44 | `(binding [ana/*cljs-ns* ana/*cljs-ns*]
45 | (ucljs/with-cljs-typed-env
46 | (let [expected-ret# ~expected-ret
47 | ; first element of this list must be the symbol ns
48 | ns-form# '(~'ns ~nsym
49 | ;~'(:refer-clojure :exclude [fn])
50 | ~'(:require [cljs.core.typed :as t :include-macros true]
51 | [cljs.core :as core]))
52 | _# (ana/analyze (ana/empty-env) ns-form#)]
53 | (t/check-form-info
54 | '~frm
55 | :expected-ret expected-ret#
56 | :expected '~syn
57 | :type-provided? ~provided?))))))
58 |
59 | (defmacro tc-e
60 | "Type check an an expression in namespace that :refer's
61 | all of clojure.core.typed (aliased to t) and aliases clojure.core
62 | to core.
63 |
64 | Takes one form and then options, and returns true if the form checks
65 | with the expected input/output types according to the provided options.
66 |
67 | The first form in the options can be a static type syntax scoped
68 | in the new namespace. This is disambiguated with a call to keyword?
69 | (literal keywords aren't valid type syntax).
70 |
71 | eg. (tc-e (+ 1 1) Num)
72 | ;=> Num
73 |
74 | Keyword Options:
75 |
76 | :expected-ret An expected ret, evaluated in the current namespace (not the new
77 | one that refers c.c.t). Cannot be provided in combination with the implicit
78 | first option as a type, as above.
79 | :ret Check the return TCResult of this expression against this ret. Evaluated
80 | in the current namespace."
81 | [frm & opts]
82 | (apply common-test/tc-e tc-common* frm opts))
83 |
84 | (defmacro is-tc-e [& body]
85 | `(test/is (do (tc-e ~@body)
86 | true)))
87 |
88 | (defmacro is-tc-err [& body]
89 | `(test/is (tc-err ~@body)))
90 |
91 | (defmacro tc-err [frm & opts]
92 | (apply common-test/tc-err tc-common* frm opts))
93 |
94 | (defn subtype? [& rs]
95 | (impl/with-cljs-impl
96 | (sub/reset-subtype-cache)
97 | (apply sub/subtype? rs)))
98 |
99 | (defmacro sub? [s t]
100 | `(impl/with-cljs-impl
101 | (sub/reset-subtype-cache)
102 | (subtype? (prs/parse-type '~s)
103 | (prs/parse-type '~t))))
104 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/analyze_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns ^:skip-wiki clojure.core.typed.analyze-cljs
10 | (:refer-clojure :exclude [extenders])
11 | (:require [clojure.core.typed.current-impl :as impl]
12 | [clojure.core.typed.util-cljs :as uc]
13 | [clojure.core.typed.analyzer-api-intercept :as api]
14 | [cljs.analyzer :as ana]
15 | [clojure.tools.reader :as reader]
16 | [clojure.java.io :as io]
17 | [cljs.env :as env]
18 | [cljs.util :as cljsu]))
19 |
20 | (declare ast-for-form)
21 |
22 | (defn ast-for-form-in-ns
23 | "Returns an AST node for the form
24 | analyzed in the given namespace"
25 | [nsym form]
26 | (uc/with-cljs-typed-env
27 | (binding [ana/*cljs-ns* nsym]
28 | (ast-for-form form {:eval-fn false}))))
29 |
30 | ; FIXME reintroduce hygienic transformation!
31 | (defn ast-for-form
32 | "Returns an AST node for the form"
33 | [form {:keys [expected eval-fn] :as opt}]
34 | ;; TODO support bindings-atom, as in c.c.t.analyze-clj
35 | ;; TODO propagate analyzer env from opt
36 | (uc/with-cljs-typed-env
37 | (let [ast (api/analyze (api/empty-env) form)]
38 | ;(prn "ast-for-form" (:op ast))
39 | (if eval-fn
40 | (eval-fn ast opt)
41 | ast))))
42 |
43 | ; like cljs.analyze/analyze-form-seq, but returns a vector of
44 | ; analysis results
45 | (defn analyze-form-seq
46 | ([forms]
47 | (analyze-form-seq forms nil))
48 | ([forms opts]
49 | (uc/with-cljs-typed-env
50 | (let [env (assoc (api/empty-env) :build-options opts)]
51 | (binding [ana/*file-defs* nil
52 | ;#?@(:clj [*unchecked-if* false])
53 | ana/*unchecked-if* false
54 | ana/*cljs-ns* 'cljs.user
55 | ana/*cljs-file* nil
56 | reader/*alias-map* (or reader/*alias-map* {})]
57 | (loop [ns nil forms forms
58 | out []]
59 | (if (some? forms)
60 | (let [form (first forms)
61 | env (assoc env :ns (ana/get-namespace ana/*cljs-ns*))
62 | ast (api/analyze env form nil opts)]
63 | (if (= (:op ast) :ns)
64 | (recur (:name ast) (next forms) (conj out ast))
65 | (recur ns (next forms) (conj out ast))))
66 | out)))))))
67 |
68 | ;; FIXME hygienic transformation
69 | (defn ast-for-ns
70 | "Returns a vector of AST nodes contained
71 | in the given namespace symbol nsym"
72 | [nsym]
73 | {:pre [(symbol? nsym)]}
74 | (analyze-form-seq (ana/forms-seq* (io/reader (cljsu/ns->source nsym)))))
75 |
76 | (let [get-namespace (delay (impl/dynaload 'cljs.analyzer/get-namespace))]
77 | (defn extenders
78 | "Returns a set of descendants for a protocol"
79 | [psym]
80 | {:pre [(symbol? psym)
81 | (namespace psym)]}
82 | (assert nil "FIXME extenders")
83 | (require 'cljs.analyzer)
84 | (or (get-in (@get-namespace (symbol (namespace psym)))
85 | [:defs (symbol (name psym)) :impls])
86 | #{})))
87 |
88 | (let [analyze-symbol (delay (impl/dynaload 'cljs.analyzer/analyze-symbol))
89 | empty-env (delay (impl/dynaload 'cljs.analyzer/empty-env))]
90 | (defn analyze-qualified-symbol
91 | "Return a var expr that the fully qualified symbol names"
92 | [sym]
93 | {:pre [(symbol? sym)]
94 | :post [(= :var (:op %))]}
95 | ;; is this still correct?
96 | (assert nil "FIXME analyze-qualified-symbol")
97 | (@analyze-symbol (@empty-env) sym)))
98 |
99 | ;(analyze-qualified-symbol 'cljs.core/ISeq)
100 | ;(analyze-qualified-symbol 'cljs.core.SubVec)
101 |
102 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 | core.typed.cljs
5 | An optional type system for ClojureScript — full system for annotating and type-checking.
6 | core.typed.cljs
7 |
8 |
9 | org.clojure
10 | core.typed-pom
11 | 0.5.4-SNAPSHOT
12 |
13 |
14 |
15 |
16 |
17 | com.theoryinpractise
18 | clojure-maven-plugin
19 | 1.7.1
20 |
21 |
22 | clojure-compile
23 | compile
24 |
25 |
26 | clojure-test
27 | test
28 |
29 |
30 |
31 | -Xmx2048m
32 | true
33 | true
34 |
35 | false
36 | true
37 |
38 | !clojure.core.typed.util-cljs
39 | !clojure.core.typed.test.cljs
40 | !cljs.core.typed.*
41 | !clojure.core.typed.base-env-cljs
42 | !clojure.core.typed.check-form-cljs
43 | !clojure.core.typed.check-ns-cljs
44 | !clojure.core.typed.test.cljs-utils
45 |
46 |
47 | clojure.core.typed.test.*
48 |
49 |
50 | src/main/clojure
51 | src/main/cljs
52 |
53 |
54 | src/test/clojure
55 | src/test/cljs
56 |
57 |
58 |
59 |
60 | maven-jar-plugin
61 | 2.4
62 |
63 |
64 | default-jar
65 | package
66 |
67 | jar
68 |
69 |
70 |
71 |
72 |
92 |
93 |
94 |
95 |
96 |
97 | org.clojure
98 | core.typed
99 | 0.5.4-SNAPSHOT
100 |
101 |
102 | org.clojure
103 | clojurescript
104 | 1.10.373
105 |
106 |
107 |
108 |
109 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/dnolen/utils/reactive.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.dnolen.utils.reactive
2 | (:refer-clojure :exclude [map filter remove distinct])
3 | (:require [goog.events :as events]
4 | [goog.events.EventType]
5 | [goog.dom :as gdom]
6 | [cljs.core.async :refer [>! go>]]
12 | [cljs.core.typed :refer [def-alias typed-deps ann]])
13 | (:import goog.events.EventType))
14 |
15 | (typed-deps cljs.core.typed.async
16 | cljs.core.typed.test.dnolen.utils.dom
17 | cljs.core.typed.test.dnolen.utils.helpers)
18 |
19 | (ann ^:no-check atom? (predicate (Atom Nothing Any)))
20 | (defn atom? [x]
21 | (instance? Atom x))
22 |
23 | (ann keyword->event-type (I (IMap Any string)
24 | [Any -> (U nil string)]))
25 | (def keyword->event-type
26 | {:keyup goog.events.EventType.KEYUP
27 | :keydown goog.events.EventType.KEYDOWN
28 | :keypress goog.events.EventType.KEYPRESS
29 | :click goog.events.EventType.CLICK
30 | :dblclick goog.events.EventType.DBLCLICK
31 | :mouseover goog.events.EventType.MOUSEOVER
32 | :mouseout goog.events.EventType.MOUSEOUT
33 | :mousemove goog.events.EventType.MOUSEMOVE})
34 |
35 | (ann listen (Fn [js/EventTarget Any -> (Chan js/Event)]
36 | [js/EventTarget Any Any -> (Chan js/Event)]))
37 | (defn listen
38 | ([el type] (listen el type false))
39 | ([el type prevent-default?]
40 | (let [out (chan> js/Event)]
41 | (events/listen el (keyword->event-type type)
42 | (fn [^{:ann 'js/EventTarget} e]
43 | (if (atom? prevent-default?)
44 | (when @prevent-default?
45 | (.preventDefault e))
46 | (when prevent-default?
47 | (.preventDefault e)))
48 | (put! out e)))
49 | out)))
50 |
51 | (ann map (All [a b]
52 | [[a -> b] (Chan a) -> (Chan b)]))
53 | (defn map [f in]
54 | (let [out (chan> b)]
55 | (go> b
56 | (loop []
57 | (if-let [x (! out (f x))
59 | (recur))
60 | (close! out))))
61 | out))
62 |
63 | (ann filter (All [a b]
64 | [[a -> Any :filters {:then (is b 0)}] (Chan a) -> (Chan b)]))
65 | (defn filter [pred in]
66 | (let [out (chan> b)]
67 | (go> b
68 | (loop []
69 | (if-let [x (! out x))
71 | (recur))
72 | (close! out))))
73 | out))
74 |
75 | (ann remove (All [a b]
76 | [[a -> Any :filters {:else (is b 0)}] (Chan a) -> (Chan b)]))
77 | (defn remove [f source]
78 | (let [out (chan> b)]
79 | (go> x
80 | (loop []
81 | (if-let [v (! out v))
83 | (recur))
84 | (close! out))))
85 | out))
86 |
87 | (ann distinct (All [x] [(Chan x) -> (Chan x)]))
88 | (defn distinct [in]
89 | (let [out (chan> x)]
90 | (go> x
91 | (loop [last nil]
92 | (if-let [x (! out x))
94 | (recur x))
95 | (close! out))))
96 | out))
97 |
98 | (ann fan-in (All [x] [(U nil (ISeqable (Chan x))) -> (Chan x)]))
99 | (defn fan-in [ins]
100 | (let [out (chan> x)]
101 | (go> x
102 | (while true
103 | (let [[x] (alts! ins)]
104 | (>! out x))))
105 | out))
106 |
107 | (ann toggle (All [x] [(Chan x) -> '{:chan (Chan Any)
108 | :control (Chan Any)}]))
109 | (defn toggle [in]
110 | (let [out (chan> Any)
111 | control (chan> Any)]
112 | (go (loop [on true]
113 | (recur
114 | (alt!
115 | in ([x] (when on (>! out x)) on)
116 | control ([x] x)))))
117 | {:chan out
118 | :control control}))
119 |
120 | (defn mouse-enter [el]
121 | (let [matcher (dom/el-matcher el)]
122 | (->> (listen el :mouseover)
123 | (filter
124 | (fn [e]
125 | (and (identical? el (.-target e))
126 | (if-let [rel (.-relatedTarget e)]
127 | (nil? (gdom/getAncestor rel matcher))
128 | true))))
129 | (map (constantly :enter)))))
130 |
131 | (defn mouse-leave [el]
132 | (let [matcher (dom/el-matcher el)]
133 | (->> (listen el :mouseout)
134 | (filter
135 | (fn [e]
136 | (and (identical? el (.-target e))
137 | (if-let [rel (.-relatedTarget e)]
138 | (nil? (gdom/getAncestor rel matcher))
139 | true))))
140 | (map (constantly :leave)))))
141 |
142 | (defn hover [el]
143 | (distinct (fan-in [(mouse-enter el) (mouse-leave el)])))
144 |
145 | (defn hover-child [el tag]
146 | (let [matcher (dom/tag-match tag)
147 | matches (dom/by-tag-name el tag)
148 | over (->> (listen el :mouseover)
149 | (map
150 | #(let [target (.-target %)]
151 | (if (matcher target)
152 | target
153 | (if-let [el (gdom/getAncestor target matcher)]
154 | el
155 | :no-match))))
156 | (remove #{:no-match})
157 | (map #(index-of matches %)))
158 | out (->> (listen el :mouseout)
159 | (filter
160 | (fn [e]
161 | (and (matcher (.-target e))
162 | (not (matcher (.-relatedTarget e))))))
163 | (map (constantly :clear)))]
164 | (distinct (fan-in [over out]))))
165 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/jsnominal_env.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns ^:skip-wiki clojure.core.typed.jsnominal-env
10 | (:refer-clojure :exclude [get-method])
11 | (:require [clojure.core.typed.type-rep :as r]
12 | [clojure.core.typed.type-ctors :as c]
13 | [clojure.core.typed.contract-utils :as con]
14 | [clojure.core.typed :as t]
15 | [clojure.core.typed.current-impl :as impl]
16 | [clojure.core.typed.env :as env])
17 | (:import (clojure.core.typed.type_rep Scope)))
18 |
19 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
20 | ;; JSNominal
21 |
22 | (t/defalias JSNominalEntry
23 | "A map entry for a JSNominal type."
24 | '{:jsnominal r/Type
25 | :fields (t/Map t/Sym (t/U Scope r/Type))
26 | :methods (t/Map t/Sym (t/U Scope r/Type))
27 | :ctors (t/U Scope r/Type nil)
28 | :ancestors (t/Set (t/U Scope r/Type))})
29 |
30 | (t/defalias JSNominalEnv
31 | "A map of symbols of JSNomainalEntry's"
32 | (t/Map t/Sym JSNominalEntry))
33 |
34 | (defn jsnominal-env []
35 | {:post [(map? %)]}
36 | (impl/jsnominal-env))
37 |
38 | (def jsnominal-env?
39 | (con/hash-c? symbol?
40 | (con/hmap-c? :jsnominal r/Type?
41 | :fields (con/hash-c? symbol? (some-fn r/Scope? r/Type?))
42 | :methods (con/hash-c? symbol? (some-fn r/Scope? r/Type?))
43 | :ctor (some-fn nil? r/Scope? r/Type?)
44 | :ancestors (con/set-c? (some-fn r/Scope? r/Type?)))))
45 |
46 | (t/ann init-jsnominal-entry [r/Type -> JSNominalEntry])
47 | (defn init-jsnominal-entry [nom]
48 | {:post [(jsnominal-env? %)]}
49 | {:jsnominal nom
50 | :fields {}
51 | :methods {}
52 | :ctors nil
53 | :ancestors #{}})
54 |
55 | (t/ann ^:no-check get-jsnominal [t/Any -> (t/Nilable r/Type)])
56 | (defn get-jsnominal
57 | "Returns the nomainal JS type with class symbol csym.
58 | Returns nil if not found."
59 | [csym]
60 | {:post [((some-fn nil? r/Type?) %)]}
61 | (-> (get (impl/jsnominal-env) csym) :jsnominal))
62 |
63 | (t/ann contains-jsnominal? [t/Any -> boolean])
64 | (defn contains-jsnominal?
65 | [csym]
66 | (boolean (get-jsnominal csym)))
67 |
68 | ;(t/ann add-jsnominal [t/Sym r/Type -> nil])
69 | ;(defn add-jsnominal [csym type]
70 | ; (assert (r/Type? type)
71 | ; (str "JS nominal" csym " not a type: " type))
72 | ; ; remove old fields etc.
73 | ; (swap! JSNOMINAL-ENV assoc-in [csym] (init-jsnominal-entry type))
74 | ; nil)
75 | ;
76 | ;(t/ann add-method [t/Sym JSNominal (t/U Scope r/Type) -> nil])
77 | ;(defn add-method
78 | ; "Add a new method to the JS nominal type csym. Assumes
79 | ; the method type is properly Scope'd"
80 | ; [csym method-sym type]
81 | ; (swap! JSNOMINAL-ENV assoc-in [csym :methods method-sym] type)
82 | ; nil)
83 | ;
84 | ;(t/ann add-field [t/Sym JSNominal (t/U Scope r/Type) -> nil])
85 | ;(defn add-field
86 | ; "Add a new field to the JS nominal type csym. Assumes
87 | ; the field type is properly Scope'd"
88 | ; [csym field-sym type]
89 | ; (swap! JSNOMINAL-ENV update-in [csym :fields field-sym] (constantly type)))
90 |
91 | (declare get-method get-field get-inherited-property)
92 |
93 | (t/ann ^:no-check get-method [t/Sym (t/U nil (t/Seqable r/Type)) t/Sym -> (t/U nil r/Type)])
94 | (defn get-method
95 | "Returns the instantiated method type named method-sym on nominal csym."
96 | [csym args method-sym]
97 | {:pre [(symbol? csym)
98 | (every? r/Type? args)
99 | (symbol? method-sym)]
100 | :post [((some-fn nil? r/Type?) %)]}
101 | (println (str "Searching " csym "#" method-sym))
102 | (if-let [tscope (get-in (impl/jsnominal-env) [csym :methods method-sym])]
103 | (c/inst-and-subst tscope args)
104 | (get-inherited-property get-method csym args method-sym)))
105 |
106 | (t/ann ^:no-check get-inherited-property [[t/Sym (t/Option (t/Seqable r/Type)) t/Sym -> (t/Option r/Type)]
107 | t/Sym (t/Option (t/Seqable r/Type)) t/Sym -> (t/Option r/Type)])
108 | (defn get-inherited-property
109 | "search for the property in the interfaces ancestors
110 | method: (get-inherited-property get-method csym args method-sym)
111 | field: (get-inherited-property get-field csym args field-sym)"
112 | [f csym args method-sym]
113 | ;(println (->> (get-in (impl/jsnominal-env) [csym :ancestors]) (map :id)))
114 | (->> (get-in (impl/jsnominal-env) [csym :ancestors])
115 | (map #(f (:id %) args method-sym))
116 | (filter identity)
117 | first))
118 |
119 | (t/ann ^:no-check get-field [t/Sym (t/U nil (t/Seqable r/Type)) t/Sym -> (t/U nil r/Type)])
120 | (defn get-field
121 | "Returns the instantiated field type named field-sym on nominal csym."
122 | [csym args field-sym]
123 | {:pre [(symbol? csym)
124 | (every? r/Type? args)
125 | (symbol? field-sym)]
126 | :post [((some-fn nil? r/Type?) %)]}
127 | (if-let [tscope (get-in (impl/jsnominal-env) [csym :fields field-sym])]
128 | (c/inst-and-subst tscope args)
129 | (get-inherited-property get-method csym args field-sym)))
130 |
131 | (t/ann ^:no-check get-ctor [t/Sym (t/U nil (t/Seqable r/Type)) -> (t/U nil r/Type)])
132 | (defn get-ctor
133 | "Returns the instantiated constructor type on nominal csym."
134 | [csym args]
135 | {:pre [(symbol? csym)
136 | (every? r/Type? args)]
137 | :post [((some-fn nil? r/Type?) %)]}
138 | (when-let [tscope (get-in (impl/jsnominal-env) [csym :ctor])]
139 | (c/inst-and-subst tscope args)))
140 |
141 | (t/ann ^:no-check reset-jsnominal! [JSNominalEnv -> nil])
142 | (defn reset-jsnominal! [m]
143 | {:pre [(jsnominal-env? m)]
144 | :post [(nil? %)]}
145 | (impl/reset-jsnominal-env! m)
146 | nil)
147 |
--------------------------------------------------------------------------------
/src/test/cljs/cljs/core/typed/test/ympbyc/test_base_env.cljs:
--------------------------------------------------------------------------------
1 | (ns cljs.core.typed.test.ympbyc.test-base-env
2 | (:require-macros [cljs.core.typed :refer [ann ann-jsnominal] :as ct])
3 | (:require [cljs.core.typed :refer [All U IFn Option I Any Seqable Vec HSequential NonEmptyASeq NonEmptySeqable Atom1 Set Coll Map] :as t]
4 | [cljs.core :refer [IVector ISeq ASeq List]]))
5 |
6 | ;;seq
7 | (ann seq-vec (NonEmptySeqable number))
8 | (def seq-vec (seq [1 2 3]))
9 |
10 | (ann seq-empty (Option (NonEmptyASeq nil)))
11 | (def seq-empty (seq []))
12 |
13 | ;;fst
14 |
15 | (ann vec-fst number)
16 | (def vec-fst (first [8]))
17 |
18 | (ann seq-fst number)
19 | (def seq-fst (first (seq [1 2 3])))
20 |
21 | (ann fst-nil nil)
22 | (def fst-nil (first nil))
23 |
24 |
25 | ;;rest
26 |
27 | (ann vec-rest (ASeq number))
28 | (def vec-rest (rest [1 2 3]))
29 |
30 | (ann seq-rest (ASeq number))
31 | (def seq-rest (rest (seq [1 2 3])))
32 |
33 | (ann rest-empty (ASeq nil))
34 | (def rest-empty (rest []))
35 |
36 |
37 | ;;last
38 |
39 | (ann vec-last number)
40 | (def vec-last (last [1 2 3]))
41 |
42 | (ann seq-last number)
43 | (def seq-last (last (seq [1 2 3])))
44 |
45 | (ann last-nil (Option number))
46 | (def last-nil (last []))
47 |
48 |
49 | ;;butlast
50 |
51 | (ann vec-butlast (ASeq number))
52 | (def vec-butlast (butlast [1 2 3]))
53 |
54 | (ann seq-butlast (ASeq number))
55 | (def vec-butlast (butlast (seq [1 2 3])))
56 |
57 | (ann butlast-empty (ASeq nil))
58 | (def butlast-empty (butlast []))
59 |
60 |
61 | ;;test if NonEmptySeqable is Seqable
62 | (ann nonemp (All [x] [(NonEmptySeqable x) -> number]))
63 | (defn foo [xs] 1)
64 |
65 | (foo (seq [1 2 3]))
66 |
67 |
68 |
69 | (ann second-vec number)
70 | (def second-vec (second [1 2 3]))
71 |
72 | (ann second-empty nil)
73 | (def second-empty (second []))
74 |
75 | (ann second-nil nil)
76 | (def second-nil (second nil))
77 |
78 | (ann second-seq (Option number))
79 | (def second-seq (second (seq [1 2 3])))
80 |
81 |
82 |
83 | (ann clj-to-jsjs Any)
84 | (def clj-to-js (clj->js {:a 1}))
85 |
86 | ;BUG: Use of js-obj triggers "js-op missing" in check_cljs
87 | ;(ann js-to-clj Any)
88 | ;(def js-to-clj (js->clj (js-obj "a" 1 "b" 2)))
89 |
90 | (ann cljs.core/nil? [Any -> boolean])
91 |
92 | (ann nil-pred-t boolean)
93 | (def nil-pred-t (nil? nil))
94 |
95 | (ann nil-pred-f boolean)
96 | (def nil-pred-f (nil? "nil"))
97 |
98 |
99 |
100 | (ann ifn?-test-t boolean)
101 | (def ifn?-test-t (ifn? (fn [x] x)))
102 |
103 | (ann ifn?-test-f boolean)
104 | (def ifn-test-f (ifn? "foo"))
105 |
106 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
107 | ;; test vars in base-env-common
108 |
109 |
110 | (ann id-test number)
111 | (def id-test (identity 8))
112 |
113 | (ann take-vec (ASeq int))
114 | (def take-vec (take 2 [1 2 3 4]))
115 |
116 |
117 | (ann drop-vec (ASeq int))
118 | (def drop-vec (drop 2 [1 2 3 4]))
119 |
120 | (ann get-set (Option int))
121 | (def get-set (get #{1 2 3} 2))
122 |
123 | (ann sym-test Symbol)
124 | (def sym-test 'foo)
125 |
126 |
127 | ;BUG: subtyping fails
128 | ;(ann atom-test (Atom1 number))
129 | ;(def atom-test (atom 3))
130 |
131 | (ann set-test (Set number))
132 | (def set-test #{5})
133 |
134 | (ann number?-t boolean)
135 | (def number?-t (number? 8))
136 |
137 | (ann number?-f boolean)
138 | (def number?-f (number? [1 2]))
139 |
140 | (ann string?-t boolean)
141 | (def string?-t (string? "hello"))
142 |
143 | (ann seq?-t boolean)
144 | (def seq-t (seq? (seq [1 2 3])))
145 |
146 | (ann seq?-f boolean)
147 | (def seq-f (seq? [1 2 3]))
148 |
149 | ;BUG: Use of `list` invokes an error
150 | ;(ann cljs.core/-conj [Any Any -> (Coll Any)])
151 | ;(ann cljs.core.List.EMPTY (List Any)) ;;this fails somehow
152 | ;(ann list?-test boolean)
153 | ;(def list?-test (list? (list 1 2 3)))
154 |
155 | (ann apply-test number)
156 | (def apply-test (apply + [2 3]))
157 |
158 | (ann apply-test-str string)
159 | (def apply-test-str (apply str ["hello, " "world"]))
160 |
161 |
162 | (ann conj-1 (IVector string))
163 | (def conj-1 (conj ["foo"] "bar"))
164 |
165 | (ann conj-2 (ASeq number))
166 | (def conj-2 (conj (seq [3 4 5]) 1 2))
167 |
168 | (ann conj-3 (ASeq (Vec number)))
169 | (def conj-3 (conj (seq [[1] [2 3]]) [8] [9]))
170 |
171 | ;BUG: this throws assert failed
172 | ;(ann conj-4 (t/Map Keyword number))
173 | ;(def conj-4 (conj {:foo 5} [:bar 8]))
174 | ;(ann conj-5 (t/Map Keyword Any))
175 | ;(def conj-5 (conj {:foo "bar"} {:baz 123}))
176 |
177 |
178 | (ann get-1 (Option number))
179 | (def get-1 (get #{1 2 3} 3))
180 |
181 | (ann get-2 boolean)
182 | (def get-2 (get {:a true :b false} :c false))
183 |
184 |
185 | (ann assoc-vec (Vec string))
186 | (def assoc-vec (assoc ["foo" "bar"] 2 "baz"))
187 |
188 | (ann assoc-map (t/Map (Vec number) string))
189 | (def assoc-map (assoc {[2 3] "foo"} [4 5] "bar"))
190 |
191 | (ann dissoc-1 (t/Map Keyword number))
192 | (def dissoc-1 (dissoc {:foo 8 :bar 9} :foo))
193 |
194 | (ann fn?-1 boolean)
195 | (def fn?-1 (fn? (fn [x y] y)))
196 |
197 | (ann fn?-2 boolean)
198 | (def fn?-2 (fn? cljs.core/map))
199 |
200 | (ann peek-1 (t/Map Keyword string))
201 | (def peek-1 (peek [{:foo "bar" :baz "zot"} {:foo "bar"}]))
202 |
203 |
204 | (ann pop-1 (Vec number))
205 | (def pop-1 (pop [1 2 3]))
206 |
207 | (ann disj-1 (Set number))
208 | (def disj-1 (disj #{1 2 3 4} 3 4))
209 |
210 |
211 | ;;jsnominals
212 | (ann-jsnominal js/Object
213 | [[]
214 | :fields {}
215 | :methods {keys (Array string)
216 | toString [-> string]}])
217 |
218 | (ann-jsnominal js/Document
219 | [[]
220 | :fields {}
221 | :methods
222 | {getElementById [string -> (cljs.core.typed/Option js/HTMLElement)]
223 | querySelector [string -> (cljs.core.typed/Option js/HTMLElement)]}
224 | :ancestors #{js/Object}])
225 |
226 | ;(ann js/document js/Document)
227 |
228 | (ann get-el [string -> (Option js/HTMLElement)])
229 | (defn get-el [sel] (.querySelector js/document sel))
230 |
231 | (ann inner-html [js/HTMLElement -> string])
232 | (defn inner-html [el] (.-innerHTML el))
233 |
234 | (ann inner-html-result string)
235 | (def inner-html-result
236 | (let [el (get-el "body")]
237 | (if el (inner-html el) "")))
238 |
239 | ;;inheritance
240 |
241 | (ann document-is-object string)
242 | (def document-is-object (.toString js/document))
243 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/core/typed/test/cljs_core.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.core.typed.test.cljs-core
2 | (:require [cljs.core.typed :as t]
3 | [cljs.core :as core]
4 | [clojure.core.typed.test.cljs-utils :refer [is-tc-e tc-e]]
5 | [clojure.test :refer :all]))
6 |
7 | ;;; defining tests this way should help estimate the coverage
8 | ;;; cljs.core vars not included in (keys @core-tests) are totally untested
9 |
10 | (def core-tests (atom {}))
11 |
12 | (defmacro add-test [f & pairs]
13 | (assert (even? (count pairs)))
14 | `(swap! core-tests conj
15 | ['~(symbol "cljs.core" (name f)) '~pairs]))
16 |
17 | ;;tests for single parameter functions
18 | (defmacro add-test1 [f & pairs]
19 | (assert (even? (count pairs)))
20 | `(swap! core-tests conj
21 | [(with-meta '~(symbol "cljs.core" (name f))
22 | {:single-arg true})
23 | '~pairs]))
24 |
25 | (defmacro run-core-tests []
26 | (cons 'do
27 | (for [[f cases] @core-tests
28 | [args expected] (partition 2 cases)]
29 | (if (:single-arg (meta f))
30 | `(is-tc-e (~f ~args) ~expected)
31 | `(is-tc-e (~f ~@args) ~expected)))))
32 |
33 |
34 | ;;; core vars test
35 |
36 | (add-test1 seq
37 | [1 2 3] (t/NonEmptySeqable t/JSNumber)
38 | [] (t/Option (t/NonEmptyASeq t/Any)))
39 |
40 | (add-test1 first
41 | [8] t/JSNumber
42 | (seq [1 2 3]) t/JSNumber
43 | nil nil)
44 |
45 | (add-test1 rest
46 | [1 2 3] (core/ASeq t/JSNumber)
47 | (seq [1 2 3]) (core/ASeq t/JSNumber)
48 | [] (core/ASeq t/Any))
49 |
50 | (add-test1 last
51 | [1 2 3] t/JSNumber
52 | (seq [1 2 3]) t/JSNumber
53 | [] (t/Option t/Any))
54 |
55 | (add-test1 butlast
56 | [1 2 3] (core/ASeq t/JSNumber)
57 | (seq [1 2 3]) (core/ASeq t/JSNumber)
58 | [] (core/ASeq t/Any))
59 |
60 | (add-test1 second
61 | [1 2 3] t/JSNumber
62 | [] nil
63 | nil nil
64 | (seq [1 2 3]) (t/Option t/JSNumber))
65 |
66 |
67 | (add-test1 clj->js
68 | {:a 1} t/Any)
69 |
70 | (add-test1 nil?
71 | nil t/JSBoolean
72 | "nil" t/JSBoolean)
73 |
74 | (add-test1 ifn?
75 | (fn [x] x) t/JSBoolean
76 | "foo" t/JSBoolean)
77 |
78 | (add-test1 identity
79 | 8 t/JSNumber
80 | "hello" t/JSString
81 | [0] (t/Vec t/JSNumber))
82 |
83 | (add-test take
84 | [2 [1 2 3 4]] (core/ASeq t/CLJSInteger))
85 |
86 | (add-test drop
87 | [2 [1 2 3 4]] (core/ASeq t/CLJSInteger))
88 |
89 | (add-test1 number?
90 | 8 t/JSBoolean
91 | [1 2] t/JSBoolean)
92 |
93 | (add-test1 string?
94 | "hello" t/JSBoolean)
95 |
96 | (add-test1 seq?
97 | (seq [1 2 3]) t/JSBoolean
98 | [1 2 3] t/JSBoolean)
99 |
100 | (add-test apply
101 | [+ [2 3]] t/JSNumber
102 | [str ["hello" "world"]] t/JSString)
103 |
104 | (add-test conj
105 | [["foo"] "bar"] (core/IVector t/JSString)
106 | [(seq [3 4 5]) 1 2] (core/ASeq t/JSNumber)
107 | [(seq [[1] [2 3]]) [8] [9]] (core/ASeq (t/Vec t/JSNumber))
108 | ;[{:foo 5} [:bar 8]] (t/Map core/Keyword t/JSNumber)
109 | ;[{:foo "bar"} {:baz 1 2 3}] (t/Map core/Keyword t/Any)
110 | )
111 |
112 | (add-test get
113 | [#{1 2 3} 3] (t/Option t/JSNumber)
114 | [{:a true :b false} :c false] t/JSBoolean)
115 |
116 | (add-test assoc
117 | [["foo" "bar"] 2 "baz"] (t/Vec t/JSString)
118 | [{[2 3] "foo"} [4 5] "bar"] (t/Map (t/Vec t/JSNumber) t/JSString))
119 |
120 | (add-test dissoc
121 | [{:foo 8 :bar 9} :foo] (t/Map core/Keyword t/JSNumber))
122 |
123 | (add-test1 fn?
124 | (fn [x y] y) t/JSBoolean
125 | cljs.core/map t/JSBoolean)
126 |
127 | (add-test1 peek
128 | [{:foo "bar" :baz "zot"} {:foo "bar"}] (t/Map core/Keyword t/JSString))
129 |
130 | (add-test1 pop
131 | [1 2 3] (t/Vec t/JSNumber))
132 |
133 | (add-test disj
134 | [#{1 2 3 4} 3 4] (t/Set t/JSNumber))
135 |
136 | (add-test1 empty?
137 | [] t/JSBoolean
138 | #{} t/JSBoolean
139 | [1] t/JSBoolean
140 | {:a 1} t/JSBoolean)
141 |
142 | (add-test1 coll?
143 | {:a 1} t/JSBoolean
144 | #{1 2} t/JSBoolean
145 | [2 3] t/JSBoolean
146 | "foo" t/JSBoolean
147 | 2 t/JSBoolean)
148 |
149 | (add-test1 map?
150 | {:a 1} t/JSBoolean
151 | {} t/JSBoolean
152 | [0 1] t/JSBoolean)
153 |
154 | (add-test1 vector?
155 | [] t/JSBoolean
156 | [1] t/JSBoolean
157 | {:a 1} t/JSBoolean
158 | "foo" t/JSBoolean)
159 |
160 | (add-test1 false?
161 | [] t/JSBoolean
162 | false t/JSBoolean
163 | true t/JSBoolean
164 | 1 t/JSBoolean)
165 |
166 | (add-test1 true?
167 | [] t/JSBoolean
168 | false t/JSBoolean
169 | true t/JSBoolean
170 | 1 t/JSBoolean)
171 |
172 | (add-test1 seq?
173 | [] t/JSBoolean
174 | #{2 3} t/JSBoolean
175 | (seq [1 2]) t/JSBoolean
176 | (seq #{2 3}) t/JSBoolean)
177 |
178 | (add-test1 boolean
179 | [] t/JSBoolean
180 | "true" t/JSBoolean
181 | :false t/JSBoolean)
182 |
183 | (add-test1 integer?
184 | 2 t/JSBoolean
185 | 1.3 t/JSBoolean
186 | "8" t/JSBoolean)
187 |
188 | (add-test contains?
189 | [[1 2 3] 2] t/JSBoolean
190 | [#{1 2} 8] t/JSBoolean
191 | [(seq []) "a"] t/JSBoolean)
192 |
193 | (add-test find
194 | [{:a 1 :b 2} :b] (t/Option (t/HVec [Keyword t/JSNumber]))
195 | [[:a :b] 0] (t/Option (t/HVec [t/CLJSInteger Keyword])))
196 |
197 | (add-test distinct?
198 | [:a :b] t/JSBoolean
199 | [[1] [1] [1]] t/JSBoolean
200 | [:a "foo" []] t/JSBoolean)
201 |
202 | (add-test compare
203 | [[1 2] [2 3]] t/JSNumber
204 | ["foo" "bar"] t/JSNumber
205 | [2 1] t/JSNumber)
206 |
207 | (add-test sort
208 | [[2 4 2 1 5 3]] (t/Option (core/ASeq t/CLJSInteger))
209 | [[:a :c :b]] (t/Option (core/ASeq Keyword))
210 | [(t/fn [x :- t/CLJSInteger y :- t/CLJSInteger] :- t/CLJSInteger (- x y))
211 | [6 1 7 3 2]] (t/Option (core/ASeq t/CLJSInteger)))
212 |
213 | (add-test1 shuffle
214 | [1 2 3 4] (t/Vec t/CLJSInteger)
215 | #{4 8 2} (t/Vec t/CLJSInteger))
216 |
217 | ;FIXME reenable after porting to tools.analyzer.js. Some issue with hygienic renaming
218 | #_(add-test reduce
219 | [(t/fn [x :- t/CLJSInteger y :- t/JSString] :- t/CLJSInteger 0)
220 | ["foo" "bar" "baz"]] t/CLJSInteger
221 | [(t/fn [x :- t/CLJSInteger y :- t/CLJSInteger] :- (core/Reduced t/CLJSInteger) (reduced 0))
222 | #{8 36 2}] t/CLJSInteger
223 | [(t/fn [x :- t/CLJSInteger y :- t/CLJSInteger] :- (core/Reduced t/CLJSInteger) (reduced 0))
224 | #{8 36 2} 0] t/CLJSInteger)
225 |
226 | (add-test reduce-kv
227 | [(t/fn [a :- t/CLJSInteger k :- Keyword v :- t/CLJSInteger] :- t/CLJSInteger (+ a v))
228 | 0 {:a 1 :b 2 :c 3}] t/CLJSInteger)
229 |
230 | (add-test <
231 | [1 5] t/JSBoolean
232 | [1.8 0.8] t/JSBoolean
233 | [1/2 3/2] t/JSBoolean)
234 |
235 | (add-test1 int
236 | 1 t/CLJSInteger)
237 |
238 | (add-test mod
239 | [8 2] t/AnyInteger
240 | [8.1 2.1] t/JSNumber)
241 |
242 | (add-test rand
243 | [] t/JSNumber
244 | [8] t/JSNumber)
245 |
246 | (add-test1 rand-int
247 | 1 t/CLJSInteger
248 | 1000 t/CLJSInteger)
249 |
250 | (add-test nthnext
251 | [nil 8] nil
252 | [#{2 3 1} 1] (t/Option (t/NonEmptyASeq t/CLJSInteger))
253 | [[1 2 3] 9] (t/Option (t/NonEmptyASeq t/CLJSInteger)))
254 |
255 | (comment add-test1 rseq
256 | [1 2 3] (t/Option (t/NonEmptyASeq t/CLJSInteger)))
257 |
258 | (add-test1 reverse
259 | [1 2 3] (core/ASeq t/CLJSInteger)
260 | {:a 1 :b 2} (core/ASeq t/Any)
261 | #{1 2 3} (core/ASeq t/CLJSInteger))
262 |
263 | (comment add-test list
264 | [1 2 3] (t/PersistentList t/CLJSInteger)
265 | [:a 2] (t/PersistentList t/Any))
266 |
267 | (add-test cons
268 | [1 [2 3]] (core/ASeq t/CLJSInteger)
269 | [[1] [[2]]] (core/ASeq (t/Vec t/CLJSInteger)))
270 |
271 |
272 |
273 |
274 |
275 |
276 |
277 | (deftest cljs-core-fns-refined-test
278 | (run-core-tests))
279 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/base_env_helper_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.base-env-helper-cljs
10 | (:refer-clojure :exclude [type])
11 | (:require [clojure.core.typed.type-rep :as r]
12 | [clojure.core.typed.parse-unparse :as prs]
13 | [clojure.core.typed.utils :as u]
14 | [clojure.core.typed.free-ops :as free-ops]
15 | [clojure.core.typed.type-ctors :as c]
16 | [clojure.core.typed.declared-kind-env :as decl-env]
17 | [clojure.core.typed.rclass-env :as rcls]
18 | [clojure.core.typed.current-impl :as impl]
19 | [clojure.core.typed.name-env :as nme-env]
20 | [clojure.core.typed.jsnominal-env :as jsnom]
21 | [clojure.core.typed.datatype-env :as dtenv]
22 | ;[clojure.core.typed.util-cljs :as ucljs]
23 | ;[cljs.analyzer :as ana]
24 | ;[cljs.compiler :as comp]
25 | [clojure.pprint :as pprint]))
26 |
27 | (defmacro alias-mappings [& args]
28 | `(impl/with-cljs-impl
29 | (let [ts# (partition 2 '~args)]
30 | (into {}
31 | (doall
32 | (for [[s# t#] ts#]
33 | (let [;desc# (-> s# meta :doc)
34 | ;doc# (str (when desc#
35 | ; (str desc# "\n\n"))
36 | ; (with-out-str (pprint/pprint t#)))
37 | ;_# (assert (and (symbol? s#)
38 | ; (namespace s#))
39 | ; "Need fully qualified symbol")
40 | ;v# (intern (find-ns (symbol (namespace s#))) (symbol (name s#)))
41 | ;_# (alter-meta! v# merge {:doc doc#})
42 | ]
43 | [(with-meta s# nil) (prs/parse-type t#)])))))))
44 |
45 | (defmacro var-mappings [& args]
46 | `(impl/with-cljs-impl
47 | (let [ts# (partition 2 '~args)]
48 | (into {}
49 | (doall
50 | (for [[s# t#] ts#]
51 | (do
52 | (assert (and (symbol? s#)
53 | (namespace s#))
54 | "Need fully qualified symbol")
55 | [s# (prs/parse-type t#)])))))))
56 |
57 | (defmacro js-var-mappings [& args]
58 | `(impl/with-cljs-impl
59 | (let [ts# (partition 2 '~args)]
60 | (into {}
61 | (doall
62 | (for [[s# t#] ts#]
63 | [s# (prs/parse-type t#)]))))))
64 |
65 | (defn declared-kind-for-protocol [binder]
66 | (let [fs (map first binder)
67 | _ (assert (every? symbol? fs) fs)
68 | vs (map (fn [[v & {:keys [variance]}]] variance) binder)]
69 | (c/TypeFn* fs vs (repeat (count vs) r/no-bounds) r/-any)))
70 |
71 | (defmacro protocol-mappings [& args]
72 | `(impl/with-cljs-impl
73 | (let [ts# (partition 2 '~args)]
74 | (into {}
75 | (doall
76 | (for [[n# [fields# & {:as opts#}]] ts#]
77 | (let [vs# (seq
78 | (for [[_# & {variance# :variance}] fields#]
79 | variance#))
80 | decl-kind# (declared-kind-for-protocol fields#)
81 | ;FIXME this is harder than it has to be
82 | ; add a Name so the methods can be parsed
83 | _# (nme-env/declare-protocol* n#)
84 | _# (when (r/TypeFn? decl-kind#)
85 | (decl-env/add-declared-kind n# decl-kind#))
86 | names# (when (seq fields#)
87 | (map first fields#))
88 | ; FIXME specify bounds
89 | bnds# (when (seq fields#)
90 | (repeat (count fields#) r/no-bounds))
91 | frees# (map r/make-F names#)
92 | methods# (free-ops/with-bounded-frees (zipmap frees# bnds#)
93 | (into {}
94 | (for [[mname# mtype#] (:methods opts#)]
95 | [mname# (prs/parse-type mtype#)])))
96 | the-var# n#
97 | on-class# (c/Protocol-var->on-class the-var#)]
98 | (decl-env/remove-declared-kind n#)
99 | [n# (c/Protocol* names# vs# frees# the-var#
100 | on-class# methods# bnds#)])))))))
101 |
102 | (defn jsnominal-entry [[n [binder & {:as opts}]]]
103 | (let [names (when (seq binder)
104 | (map first binder))
105 | {vs :variances
106 | names :names
107 | bnds :bnds}
108 | (when (seq binder)
109 | ; don't bound frees because mutually dependent bounds are problematic
110 | ; FIXME ... Or is this just laziness?
111 | (let [b (free-ops/with-free-symbols names
112 | (mapv prs/parse-tfn-binder binder))]
113 | {:variances (map :variance b)
114 | :names (map :nme b)
115 | :bnds (map :bound b)}))
116 | frees (map r/make-F names)
117 | methods (free-ops/with-bounded-frees (zipmap frees bnds)
118 | (into {}
119 | (for [[mname mtype] (:methods opts)]
120 | [mname (c/abstract-many names (prs/parse-type mtype))])))
121 | fields (free-ops/with-bounded-frees (zipmap frees bnds)
122 | (into {}
123 | (for [[mname mtype] (:fields opts)]
124 | [mname (c/abstract-many names (prs/parse-type mtype))])))
125 | ctor (when-let [ctor (:ctor opts)]
126 | (free-ops/with-bounded-frees (zipmap frees bnds)
127 | (c/abstract-many names (prs/parse-type ctor))))
128 | ancestors (free-ops/with-bounded-frees (zipmap frees bnds)
129 | (into #{}
130 | (for [mtype (:ancestors opts)]
131 | (c/abstract-many names (prs/parse-type mtype)))))]
132 | (decl-env/remove-declared-kind n)
133 | [n {:jsnominal (c/JSNominal* names vs frees n bnds)
134 | :fields fields
135 | :methods methods
136 | :ctor ctor
137 | :ancestors ancestors}]))
138 |
139 |
140 | (defmacro jsnominal-mappings [& args]
141 | `(impl/with-cljs-impl
142 | (let [ts# (partition 2 '~args)]
143 | (into {}
144 | (doall
145 | (for [t# ts#]
146 | (jsnominal-entry t#)))))))
147 |
148 | (defmacro datatype-mappings [& args]
149 | `(impl/with-cljs-impl
150 | (let [ts# (partition 2 '~args)]
151 | (into {}
152 | (doall
153 | (for [[n# [binder# & {record?# :record? :as opts#}]] ts#]
154 | (let [names# (when (seq binder#)
155 | (map first binder#))
156 | {vs# :variances
157 | names# :names
158 | bnds# :bnds}
159 | (when (seq binder#)
160 | ; don't bound frees because mutually dependent bounds are problematic
161 | ; FIXME ... Or is this just laziness?
162 | (let [b# (free-ops/with-free-symbols names#
163 | (mapv prs/parse-tfn-binder binder#))]
164 | {:variances (seq (map :variance b#))
165 | :names (seq (map :nme b#))
166 | :bnds (seq (map :bound b#))}))
167 | frees# (seq (map r/make-F names#))
168 | fields# (free-ops/with-bounded-frees (zipmap frees# bnds#)
169 | (into {}
170 | (for [[mname# mtype#] (:fields opts#)]
171 | [mname# (prs/parse-type mtype#)])))]
172 | (decl-env/remove-declared-kind n#)
173 | [n# (c/DataType* names# vs# frees# n# bnds# fields# (boolean record?#))])))))))
174 |
175 | (defmacro jsenv-mappings [& args]
176 | `(impl/with-cljs-impl
177 | (let [ts# (partition 2 '~args)]
178 | (into {}
179 | (doall
180 | (for [[s# t#] ts#]
181 | [s# (prs/parse-type t#)]))))))
182 |
--------------------------------------------------------------------------------
/src/test/clojure/clojure/core/typed/test/cljs.clj:
--------------------------------------------------------------------------------
1 | (ns clojure.core.typed.test.cljs
2 | (:require [clojure.core.typed.test.cljs-utils :refer :all]
3 | [clojure.test :refer :all]
4 | [clojure.core.typed.type-rep :as r]
5 | [clojure.core.typed.subtype :as sub]
6 | [cljs.core.typed :as t]
7 | [clojure.core.typed.util-cljs :as ucljs]
8 | [clojure.core.typed.current-impl :as impl]
9 | [clojure.core.typed.type-ctors :as c]
10 | [clojure.core.typed.parse-unparse :as prs]
11 |
12 | [clojure.core.typed.base-env-common :refer [delay-and-cache-env]
13 | :as common]
14 | [clojure.core.typed.var-env :as var-env]
15 | [clojure.core.typed.test.cljs-core :as core-test]
16 | [clojure.core.typed.analyzer-api-intercept :as fake-ana-api]))
17 |
18 | (deftest parse-prims-cljs-test
19 | (is-cljs (= (prs/parse-cljs 'cljs.core.typed/JSNumber)
20 | (r/JSNumber-maker)))
21 | (is-cljs (= (prs/parse-cljs 'cljs.core.typed/CLJSInteger)
22 | (r/CLJSInteger-maker)))
23 | (is-cljs (= (prs/parse-cljs 'cljs.core.typed/JSBoolean)
24 | (r/JSBoolean-maker)))
25 | (is-cljs (= (prs/parse-cljs 'cljs.core.typed/JSObject)
26 | (r/JSObject-maker)))
27 | (is-cljs (= (prs/parse-cljs 'cljs.core.typed/JSString)
28 | (r/JSString-maker))))
29 |
30 | (deftest parse-array-cljs-test
31 | (is-cljs (= (prs/parse-cljs '(Array cljs.core.typed/JSNumber))
32 | (r/ArrayCLJS-maker (prs/parse-cljs 'cljs.core.typed/JSNumber)
33 | (prs/parse-cljs 'cljs.core.typed/JSNumber)))))
34 |
35 | (deftest unparse-prims-cljs-test
36 | (is-cljs (= 'cljs.core.typed/JSNumber
37 | (prs/unparse-type (prs/parse-cljs 'cljs.core.typed/JSNumber))))
38 | (is-cljs (= 'cljs.core.typed/JSBoolean
39 | (prs/unparse-type (prs/parse-cljs 'cljs.core.typed/JSBoolean))))
40 | (is-cljs (= 'cljs.core.typed/CLJSInteger
41 | (prs/unparse-type (prs/parse-cljs 'cljs.core.typed/CLJSInteger))))
42 | (is-cljs (= '(Array cljs.core.typed/JSNumber)
43 | (prs/unparse-type (prs/parse-cljs '(Array cljs.core.typed/JSNumber)))))
44 | (is-cljs (= '(Array2 cljs.core.typed/JSNumber cljs.core.typed/JSBoolean)
45 | (prs/unparse-type (prs/parse-cljs '(Array2 cljs.core.typed/JSNumber cljs.core.typed/JSBoolean))))))
46 |
47 | (deftest subtype-prims-cljs-test
48 | (is-cljs (sub/subtype? (r/-val 1) (prs/parse-cljs 'cljs.core.typed/JSNumber))))
49 |
50 | ;FIXME
51 | #_
52 | (deftest throw-test
53 | (is-tc-e (throw (js/JSError. "foo"))
54 | t/Nothing))
55 |
56 | (deftest ann-test
57 | (is-tc-e (do (t/ann foo t/JSNumber)
58 | (def foo 1)))
59 | (is-tc-err (do (t/ann foo t/JSNumber)
60 | (def foo nil))))
61 |
62 | (deftest check-ns-test
63 | (is-cljs (t/check-ns* 'cljs.core.typed.test.ann)))
64 |
65 | (deftest parse-protocol-test
66 | (is-cljs (prs/parse-cljs '(cljs.core/IMap cljs.core.typed/JSNumber cljs.core.typed/JSNumber))))
67 |
68 | (deftest Protocol-of-test
69 | (is-cljs (c/Protocol-of 'cljs.core/IMap [(r/JSNumber-maker)
70 | (r/JSNumber-maker)])))
71 |
72 | (deftest heterogeneous-ds-test
73 | (is-tc-e [1 2]
74 | '[t/JSNumber t/JSNumber])
75 | (is-tc-e [1 2]
76 | (IVector t/JSNumber))
77 | (is-tc-e {:a 1}
78 | '{:a t/JSNumber})
79 | (is-tc-e {1 1}
80 | (IMap t/JSNumber t/JSNumber))
81 | (is-tc-e #{1}
82 | (ISet t/JSNumber))
83 | (is-tc-e (let [a 1] #{1 a})
84 | (ISet t/JSNumber)))
85 |
86 | (deftest js*-test
87 | (is-tc-e (+ 1 1)))
88 |
89 | (deftest fn-test
90 | (is-tc-e (fn a [b] a))
91 | (is-tc-e (fn [a] a)
92 | (t/All [x] [x -> x])))
93 |
94 | (deftest inst-test
95 | (is-tc-e (let [f (-> (fn [a] a)
96 | (t/ann-form (t/All [x] [x -> x])))]
97 | ((t/inst f t/JSNumber) 1))
98 | t/JSNumber))
99 |
100 | (deftest letfn-test
101 | (is-tc-e (t/letfn> [a :- (t/All [x] [x -> x])
102 | (a [b] b)]
103 | (a 1))))
104 |
105 | ;;commenting-out this test because just :require -ing cljs.core.async fails with internal error
106 | #_(deftest async-test
107 | (is-cljs (t/check-ns* 'cljs.core.typed.async)))
108 |
109 | (deftest inline-annotation-test
110 | ; code from David Nolen's blog
111 | ;FIXME
112 | #_(is-tc-e
113 | (defn ^{:ann '[(t/U nil (ISeqable t/Any)) t/Any -> cljs.core.typed/CLJSInteger]}
114 | index-of [xs x]
115 | (let [len (count xs)]
116 | (t/loop>
117 | [i :- cljs.core.typed/CLJSInteger, 0]
118 | (if (< i len)
119 | (if (= (nth xs i) x)
120 | i
121 | (recur (inc i)))
122 | -1))))))
123 |
124 | #_
125 | (deftest simple-polymorphic-test
126 | (is-cljs (t/check-ns* 'cljs.core.typed.test.identity)))
127 |
128 | (deftest value-supertype-test
129 | (is-tc-e 'a Symbol)
130 | (is-tc-e :a Keyword)
131 | (is-tc-e 1 t/CLJSInteger)
132 | (is-tc-e 1.1 t/JSNumber)
133 | (is-tc-e 1 t/JSNumber)
134 | (is-tc-e true t/JSBoolean)
135 | (is-tc-e "a" t/JSString))
136 |
137 | (deftest ns-deps-test
138 | (is (t/check-ns* 'cljs.core.typed.test.dep-one))
139 | (is (t/check-ns* 'cljs.core.typed.test.dep-two)))
140 |
141 | (deftest hvec-infer
142 | (is-tc-e (fn [a]
143 | (a [1 2]))
144 | [[(cljs.core/IVector t/Any) -> t/Any]
145 | -> t/Any])
146 | (is-tc-e (fn [a]
147 | (a [1 2]))
148 | [(t/All [x] [(cljs.core/IVector x) -> x])
149 | -> t/Any]))
150 |
151 | (deftest seq-test
152 | (is-tc-e [1 2 3] (t/Coll cljs.core.typed/CLJSInteger))
153 | (is-tc-e [1 2 3] (t/Seqable cljs.core.typed/CLJSInteger)) ;;not sure if it should be...
154 | (is-tc-e (seq [1 2 3]) (t/NonEmptyASeq cljs.core.typed/CLJSInteger)))
155 |
156 | ;(t/check-ns* 'cljs.core.typed.test.dnolen.utils.dom)
157 | ;(t/check-ns* 'cljs.core.typed.test.dnolen.utils.reactive)
158 | ;(t/check-ns* 'cljs.core.typed.test.dnolen.utils.helpers)
159 | ;(t/check-ns* 'cljs.core.typed.async)
160 |
161 |
162 | (deftest core-fns-test
163 | (t/check-ns* 'cljs.core.typed.test.ympbyc.test-base-env))
164 |
165 | (deftest ctyp-255-cljs-test
166 | (testing "unparsing protocols is fully qualified in :unknown"
167 | (is-cljs (= (prs/unparse-type (c/Protocol-of 'cljs.core/ISet [r/-any]))
168 | '(cljs.core/ISet clojure.core.typed/Any)))))
169 |
170 |
171 | (def nodes #{:binding :case :case-node :case-test :case-then :const :def :defrecord :deftype :do :fn :fn-method :host-call :host-field :if :invoke :js :js-array :js-object :js-var :let :letfn :local :loop :map :new :no-op :ns :ns* :quote :recur :set :set! :the-var :throw :try :var :vector :with-meta
172 | })
173 |
174 | (deftest check-case-coverage-test
175 | (fake-ana-api/reset-found)
176 |
177 | ;;let
178 | (is-tc-e (let [x 0
179 | y x]
180 | y)
181 | t/JSNumber)
182 |
183 | ;;case
184 | (is-tc-e (fn [x] (case x
185 | 0 "zero"
186 | "non-zero"))
187 | [t/JSNumber -> cljs.core.typed/JSString])
188 |
189 | ;;def
190 | (tc-e (def x 1))
191 |
192 | ;;fn
193 | (tc-e (fn [x] x))
194 |
195 |
196 | ;;const
197 | (is-tc-e 1 t/JSNumber)
198 |
199 | ;;if
200 | (tc-e (if 1 1 0))
201 |
202 | ;;letfn
203 | (tc-e (t/letfn> [foo :- [t/JSNumber -> t/JSNumber]
204 | (foo [x] x)]
205 | (foo 2)))
206 |
207 | ;;loop
208 | (is-tc-e (t/loop [a :- t/JSNumber 1
209 | b :- (t/U nil t/JSNumber) nil]
210 | (if b (str a)
211 | (recur 1 1)))
212 | t/Str)
213 |
214 | ;;map
215 | (tc-e {:name "Bob" :job "unemployed"})
216 |
217 | ;;set
218 | (tc-e #{1 2 3})
219 |
220 | ;;quote
221 | (tc-e '(1 2 3))
222 |
223 |
224 |
225 | (print "MISSING NODES (fake ERROR): ")
226 | (doseq [op (sort (clojure.set/difference nodes @fake-ana-api/ops-found))]
227 | (print (str op " ")))
228 | (println))
229 |
230 | (deftest HSequential-parse-test
231 | (is-tc-e [] (t/HSequential [t/Any *]))
232 | (is-tc-e '() (t/HSeq [t/Any *]))
233 | (is-tc-e #{:kw} (t/HSet [:kw]))
234 | ;; FIXME Value/Val parsing
235 | #_(is-tc-e {:a 1} (t/HMap :mandatory {:a (t/Value 1)}))
236 | #_(is-tc-e {:a 1} (t/HMap :mandatory {:a (t/Val 1)}))
237 | (is-tc-e {:a 1}
238 | (t/Rec [x] (t/U nil (t/HMap :mandatory {:a t/JSNumber} :optional {:b x}))))
239 | )
240 |
241 | (deftest undefined-test
242 | (is-tc-err nil t/JSUndefined)
243 | (is-tc-err nil t/JSNull)
244 | (is (not (sub? nil cljs.core.typed/JSNull)))
245 | (is (not (sub? nil cljs.core.typed/JSUndefined)))
246 | (is (sub? cljs.core.typed/JSUndefined nil))
247 | (is (sub? cljs.core.typed/JSNull nil))
248 | (is-tc-e (t/fn [a :- t/JSUndefined] :- nil
249 | a))
250 | (is-tc-e (t/fn [a :- t/JSNull] :- nil
251 | a))
252 | (is-tc-err (t/fn [a :- t/JSNull] :- t/JSUndefined
253 | a))
254 | (is-tc-err (t/fn [a :- t/JSUndefined] :- t/JSNull
255 | a))
256 | (is-tc-err (when (undefined? nil)
257 | :kw)
258 | nil)
259 | (is-tc-e (t/fn [a :- t/JSNull]
260 | (when (undefined? a)
261 | :kw))
262 | [t/JSNull :-> nil])
263 | (is-tc-e (t/fn [a :- t/JSUndefined]
264 | (when (undefined? a)
265 | :kw))
266 | [t/JSUndefined :-> ':kw])
267 | (is-tc-e (do
268 | (t/ann ^:no-check a t/JSUndefined)
269 | (def a nil)
270 | a)
271 | nil)
272 | (is-tc-e (t/fn [a :- (t/U (cljs.core/IVector t/Any) t/JSUndefined)]
273 | (if a
274 | (t/ann-form a (cljs.core/IVector t/Any))
275 | (t/ann-form a t/JSUndefined))))
276 | )
277 |
278 | (deftest ratio-test
279 | (is-tc-e 1/2 t/JSNumber))
280 |
281 | (deftest goog-imports
282 | (is-cljs (t/check-ns* 'cljs.core.typed.test.goog-import)))
283 |
284 | (deftest jsobj-test
285 | (is-cljs (t/check-ns* 'cljs.core.typed.test.js-obj)))
286 |
--------------------------------------------------------------------------------
/epl-v10.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Eclipse Public License - Version 1.0
8 |
25 |
26 |
27 |
28 |
29 |
30 | Eclipse Public License - v 1.0
31 |
32 | THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
33 | PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR
34 | DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS
35 | AGREEMENT.
36 |
37 | 1. DEFINITIONS
38 |
39 | "Contribution" means:
40 |
41 | a) in the case of the initial Contributor, the initial
42 | code and documentation distributed under this Agreement, and
43 | b) in the case of each subsequent Contributor:
44 | i) changes to the Program, and
45 | ii) additions to the Program;
46 | where such changes and/or additions to the Program
47 | originate from and are distributed by that particular Contributor. A
48 | Contribution 'originates' from a Contributor if it was added to the
49 | Program by such Contributor itself or anyone acting on such
50 | Contributor's behalf. Contributions do not include additions to the
51 | Program which: (i) are separate modules of software distributed in
52 | conjunction with the Program under their own license agreement, and (ii)
53 | are not derivative works of the Program.
54 |
55 | "Contributor" means any person or entity that distributes
56 | the Program.
57 |
58 | "Licensed Patents" mean patent claims licensable by a
59 | Contributor which are necessarily infringed by the use or sale of its
60 | Contribution alone or when combined with the Program.
61 |
62 | "Program" means the Contributions distributed in accordance
63 | with this Agreement.
64 |
65 | "Recipient" means anyone who receives the Program under
66 | this Agreement, including all Contributors.
67 |
68 | 2. GRANT OF RIGHTS
69 |
70 | a) Subject to the terms of this Agreement, each
71 | Contributor hereby grants Recipient a non-exclusive, worldwide,
72 | royalty-free copyright license to reproduce, prepare derivative works
73 | of, publicly display, publicly perform, distribute and sublicense the
74 | Contribution of such Contributor, if any, and such derivative works, in
75 | source code and object code form.
76 |
77 | b) Subject to the terms of this Agreement, each
78 | Contributor hereby grants Recipient a non-exclusive, worldwide,
79 | royalty-free patent license under Licensed Patents to make, use, sell,
80 | offer to sell, import and otherwise transfer the Contribution of such
81 | Contributor, if any, in source code and object code form. This patent
82 | license shall apply to the combination of the Contribution and the
83 | Program if, at the time the Contribution is added by the Contributor,
84 | such addition of the Contribution causes such combination to be covered
85 | by the Licensed Patents. The patent license shall not apply to any other
86 | combinations which include the Contribution. No hardware per se is
87 | licensed hereunder.
88 |
89 | c) Recipient understands that although each Contributor
90 | grants the licenses to its Contributions set forth herein, no assurances
91 | are provided by any Contributor that the Program does not infringe the
92 | patent or other intellectual property rights of any other entity. Each
93 | Contributor disclaims any liability to Recipient for claims brought by
94 | any other entity based on infringement of intellectual property rights
95 | or otherwise. As a condition to exercising the rights and licenses
96 | granted hereunder, each Recipient hereby assumes sole responsibility to
97 | secure any other intellectual property rights needed, if any. For
98 | example, if a third party patent license is required to allow Recipient
99 | to distribute the Program, it is Recipient's responsibility to acquire
100 | that license before distributing the Program.
101 |
102 | d) Each Contributor represents that to its knowledge it
103 | has sufficient copyright rights in its Contribution, if any, to grant
104 | the copyright license set forth in this Agreement.
105 |
106 | 3. REQUIREMENTS
107 |
108 | A Contributor may choose to distribute the Program in object code
109 | form under its own license agreement, provided that:
110 |
111 | a) it complies with the terms and conditions of this
112 | Agreement; and
113 |
114 | b) its license agreement:
115 |
116 | i) effectively disclaims on behalf of all Contributors
117 | all warranties and conditions, express and implied, including warranties
118 | or conditions of title and non-infringement, and implied warranties or
119 | conditions of merchantability and fitness for a particular purpose;
120 |
121 | ii) effectively excludes on behalf of all Contributors
122 | all liability for damages, including direct, indirect, special,
123 | incidental and consequential damages, such as lost profits;
124 |
125 | iii) states that any provisions which differ from this
126 | Agreement are offered by that Contributor alone and not by any other
127 | party; and
128 |
129 | iv) states that source code for the Program is available
130 | from such Contributor, and informs licensees how to obtain it in a
131 | reasonable manner on or through a medium customarily used for software
132 | exchange.
133 |
134 | When the Program is made available in source code form:
135 |
136 | a) it must be made available under this Agreement; and
137 |
138 | b) a copy of this Agreement must be included with each
139 | copy of the Program.
140 |
141 | Contributors may not remove or alter any copyright notices contained
142 | within the Program.
143 |
144 | Each Contributor must identify itself as the originator of its
145 | Contribution, if any, in a manner that reasonably allows subsequent
146 | Recipients to identify the originator of the Contribution.
147 |
148 | 4. COMMERCIAL DISTRIBUTION
149 |
150 | Commercial distributors of software may accept certain
151 | responsibilities with respect to end users, business partners and the
152 | like. While this license is intended to facilitate the commercial use of
153 | the Program, the Contributor who includes the Program in a commercial
154 | product offering should do so in a manner which does not create
155 | potential liability for other Contributors. Therefore, if a Contributor
156 | includes the Program in a commercial product offering, such Contributor
157 | ("Commercial Contributor") hereby agrees to defend and
158 | indemnify every other Contributor ("Indemnified Contributor")
159 | against any losses, damages and costs (collectively "Losses")
160 | arising from claims, lawsuits and other legal actions brought by a third
161 | party against the Indemnified Contributor to the extent caused by the
162 | acts or omissions of such Commercial Contributor in connection with its
163 | distribution of the Program in a commercial product offering. The
164 | obligations in this section do not apply to any claims or Losses
165 | relating to any actual or alleged intellectual property infringement. In
166 | order to qualify, an Indemnified Contributor must: a) promptly notify
167 | the Commercial Contributor in writing of such claim, and b) allow the
168 | Commercial Contributor to control, and cooperate with the Commercial
169 | Contributor in, the defense and any related settlement negotiations. The
170 | Indemnified Contributor may participate in any such claim at its own
171 | expense.
172 |
173 | For example, a Contributor might include the Program in a commercial
174 | product offering, Product X. That Contributor is then a Commercial
175 | Contributor. If that Commercial Contributor then makes performance
176 | claims, or offers warranties related to Product X, those performance
177 | claims and warranties are such Commercial Contributor's responsibility
178 | alone. Under this section, the Commercial Contributor would have to
179 | defend claims against the other Contributors related to those
180 | performance claims and warranties, and if a court requires any other
181 | Contributor to pay any damages as a result, the Commercial Contributor
182 | must pay those damages.
183 |
184 | 5. NO WARRANTY
185 |
186 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS
187 | PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
188 | OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION,
189 | ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY
190 | OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely
191 | responsible for determining the appropriateness of using and
192 | distributing the Program and assumes all risks associated with its
193 | exercise of rights under this Agreement , including but not limited to
194 | the risks and costs of program errors, compliance with applicable laws,
195 | damage to or loss of data, programs or equipment, and unavailability or
196 | interruption of operations.
197 |
198 | 6. DISCLAIMER OF LIABILITY
199 |
200 | EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT
201 | NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT,
202 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING
203 | WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF
204 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
205 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR
206 | DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
207 | HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
208 |
209 | 7. GENERAL
210 |
211 | If any provision of this Agreement is invalid or unenforceable under
212 | applicable law, it shall not affect the validity or enforceability of
213 | the remainder of the terms of this Agreement, and without further action
214 | by the parties hereto, such provision shall be reformed to the minimum
215 | extent necessary to make such provision valid and enforceable.
216 |
217 | If Recipient institutes patent litigation against any entity
218 | (including a cross-claim or counterclaim in a lawsuit) alleging that the
219 | Program itself (excluding combinations of the Program with other
220 | software or hardware) infringes such Recipient's patent(s), then such
221 | Recipient's rights granted under Section 2(b) shall terminate as of the
222 | date such litigation is filed.
223 |
224 | All Recipient's rights under this Agreement shall terminate if it
225 | fails to comply with any of the material terms or conditions of this
226 | Agreement and does not cure such failure in a reasonable period of time
227 | after becoming aware of such noncompliance. If all Recipient's rights
228 | under this Agreement terminate, Recipient agrees to cease use and
229 | distribution of the Program as soon as reasonably practicable. However,
230 | Recipient's obligations under this Agreement and any licenses granted by
231 | Recipient relating to the Program shall continue and survive.
232 |
233 | Everyone is permitted to copy and distribute copies of this
234 | Agreement, but in order to avoid inconsistency the Agreement is
235 | copyrighted and may only be modified in the following manner. The
236 | Agreement Steward reserves the right to publish new versions (including
237 | revisions) of this Agreement from time to time. No one other than the
238 | Agreement Steward has the right to modify this Agreement. The Eclipse
239 | Foundation is the initial Agreement Steward. The Eclipse Foundation may
240 | assign the responsibility to serve as the Agreement Steward to a
241 | suitable separate entity. Each new version of the Agreement will be
242 | given a distinguishing version number. The Program (including
243 | Contributions) may always be distributed subject to the version of the
244 | Agreement under which it was received. In addition, after a new version
245 | of the Agreement is published, Contributor may elect to distribute the
246 | Program (including its Contributions) under the new version. Except as
247 | expressly stated in Sections 2(a) and 2(b) above, Recipient receives no
248 | rights or licenses to the intellectual property of any Contributor under
249 | this Agreement, whether expressly, by implication, estoppel or
250 | otherwise. All rights in the Program not expressly granted under this
251 | Agreement are reserved.
252 |
253 | This Agreement is governed by the laws of the State of New York and
254 | the intellectual property laws of the United States of America. No party
255 | to this Agreement will bring a legal action under this Agreement more
256 | than one year after the cause of action arose. Each party waives its
257 | rights to a jury trial in any resulting litigation.
258 |
259 |
260 |
261 |
262 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/check_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.check-cljs
10 | (:require [clojure.core.typed :as t]
11 | [clojure.core.typed.ast-utils :as ast-u]
12 | [clojure.core.typed.check-below :as below]
13 | [clojure.core.typed.local-result :as local-result]
14 | [clojure.core.typed.constant-type :as constant-type]
15 | [clojure.core.typed.check :as chk]
16 | [clojure.core.typed.check.binding :as binding]
17 | [clojure.core.typed.check.def :as def]
18 | [clojure.core.typed.check.do :as do]
19 | [clojure.core.typed.check.dot-cljs :as dot]
20 | [clojure.core.typed.check.const :as const]
21 | [clojure.core.typed.check.fn :as fn]
22 | [clojure.core.typed.check.fn-method-utils :as fn-method-u]
23 | [clojure.core.typed.check.funapp :as funapp]
24 | [clojure.core.typed.check.if :as if]
25 | [clojure.core.typed.check.let :as let]
26 | [clojure.core.typed.check.letfn :as letfn]
27 | [clojure.core.typed.check.local :as local]
28 | [clojure.core.typed.check.loop :as loop]
29 | [clojure.core.typed.check.map :as map]
30 | [clojure.core.typed.check.print-env :as pr-env]
31 | [clojure.core.typed.check.recur :as recur]
32 | [clojure.core.typed.check.recur-utils :as recur-u]
33 | [clojure.core.typed.check.set :as set]
34 | [clojure.core.typed.check.set-bang :as set!]
35 | [clojure.core.typed.check.throw :as throw]
36 | [clojure.core.typed.check.quote :as quote]
37 | [clojure.core.typed.check.vector :as vec]
38 | [clojure.core.typed.check.with-meta :as with-meta]
39 | [clojure.core.typed.check.special.fn :as special-fn]
40 | [clojure.core.typed.check.special.ann-form :as ann-form]
41 | [clojure.core.typed.check.special.tc-ignore :as tc-ignore]
42 | [clojure.core.typed.check.special.loop :as special-loop]
43 | [clojure.core.typed.errors :as err]
44 | [clojure.core.typed.check.utils :as cu]
45 | [clojure.core.typed.contract-utils :as con]
46 | [clojure.core.typed.type-rep :as r :refer [ret ret-t ret-o]]
47 | [clojure.core.typed.type-ctors :as c]
48 | [clojure.core.typed.subtype :as sub]
49 | [clojure.core.typed.tc-equiv :as equiv]
50 | [clojure.core.typed.utils :as u :refer [expr-type]]
51 | [clojure.core.typed.util-vars :as vs]
52 | [clojure.core.typed.var-env :as var-env]
53 | [clojure.core.typed.parse-unparse :as prs]
54 | [clojure.core.typed.lex-env :as lex]
55 | [clojure.core.typed.filter-rep :as f]
56 | [clojure.core.typed.filter-ops :as fl]
57 | [clojure.core.typed.inst :as inst]
58 | [clojure.core.typed.object-rep :as o]
59 | [clojure.core.typed.jsnominal-env :as jsnom]
60 | [clojure.core.typed.filter-ops :as fo]
61 | [clojure.core.typed.object-rep :a obj]
62 | [clojure.core.typed.analyze-cljs :as ana]
63 | [clojure.string :as c-str]))
64 |
65 | (declare check)
66 |
67 | (defn check-expr [{:keys [env] :as expr} & [expected]]
68 | (binding [vs/*current-env* (if (:line env) env vs/*current-env*)
69 | vs/*current-expr* expr]
70 | (check expr expected)))
71 |
72 | (defn check-asts [asts]
73 | (mapv check-expr asts))
74 |
75 | (defn check-ns [nsym]
76 | {:pre [(symbol? nsym)]
77 | :post [(nil? %)]}
78 | (cu/check-ns-and-deps*
79 | nsym
80 | {:ast-for-ns ana/ast-for-ns
81 | :check-asts check-asts
82 | :check-ns check-ns}))
83 |
84 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
85 | ;;; Check CLJS AST
86 |
87 | (defmulti -check (fn [expr expected]
88 | (:op expr)))
89 |
90 | (defn check [expr & [expected]]
91 | (-check expr expected))
92 |
93 | (defmethod -check :no-op
94 | [expr expected]
95 | (assoc expr
96 | expr-type (below/maybe-check-below
97 | (ret r/-any)
98 | expected)))
99 |
100 | (defmethod -check :const
101 | [{:keys [val] :as expr} expected]
102 | ;; FIXME probably want a custom `constant-type` function
103 | (const/check-const constant-type/constant-type false expr expected))
104 |
105 | (defmethod -check :vector
106 | [expr expected]
107 | (vec/check-vector check expr expected))
108 |
109 | (defmethod -check :set
110 | [expr expected]
111 | (set/check-set check expr expected))
112 |
113 | (defmethod -check :map
114 | [expr expected]
115 | (map/check-map check expr expected))
116 |
117 | (defmethod -check :def
118 | [{:keys [init] :as expr} expected]
119 | (if init
120 | (def/check-normal-def check expr expected)
121 | (assoc expr
122 | u/expr-type (below/maybe-check-below
123 | (ret r/-any)
124 | expected))))
125 |
126 | (defmethod -check :js
127 | [{:keys [js-op args env] :as expr} expected]
128 | (cond
129 | js-op (let [res (expr-type (check {:op :invoke
130 | :from-js-op expr
131 | :env env
132 | :children [:fn :args]
133 | :fn {:op :var
134 | :env env
135 | :name js-op}
136 | :args args}
137 | expected))]
138 | (assoc expr
139 | u/expr-type res))
140 | :else (do (u/tc-warning (str "js-op missing, inferring Unchecked"))
141 | (assoc expr
142 | u/expr-type (below/maybe-check-below
143 | (r/ret (r/-unchecked))
144 | expected)))))
145 |
146 | (defmulti invoke-special (fn [{{:keys [op] :as fexpr} :fn :as expr} & expected]
147 | (when (= :var op)
148 | (:name fexpr))))
149 |
150 | (defmethod invoke-special :default [& _] ::not-special)
151 |
152 | (defmethod invoke-special 'cljs.core.typed/print-env
153 | [{[{debug-string :form :as texpr} :as args] :args :as expr} & [expected]]
154 | (assert (= 1 (count args)))
155 | (assert (string? debug-string))
156 | ;DO NOT REMOVE
157 | (pr-env/print-env*)
158 | ;DO NOT REMOVE
159 | (assoc expr
160 | expr-type (ret r/-any)))
161 |
162 | (defmethod invoke-special 'cljs.core.typed/inst-poly
163 | [{[pexpr targs-expr :as args] :args :as expr} & [expected]]
164 | (assert (#{2} (count args)) "Wrong arguments to inst")
165 | (let [ptype (let [t (-> (check pexpr) expr-type ret-t)]
166 | (c/fully-resolve-type t))
167 | _ (assert ((some-fn r/Poly? r/PolyDots?) ptype))
168 | targs (binding [prs/*parse-type-in-ns* (cu/expr-ns expr)]
169 | (mapv prs/parse-type (-> targs-expr :expr :form)))]
170 | (assoc expr
171 | expr-type (ret (inst/manual-inst ptype targs)))))
172 |
173 | (defmethod invoke-special 'cljs.core.typed/loop>-ann
174 | [{[expr {{expected-bnds-syn :expr} :form}] :args :as dummy-expr} & [expected]]
175 | (let [expected-bnds (binding [prs/*parse-type-in-ns* (cu/expr-ns dummy-expr)]
176 | (mapv prs/parse-type expected-bnds-syn))]
177 | ;loop may be nested, type the first loop found
178 | (binding [recur-u/*loop-bnd-anns* expected-bnds]
179 | (check expr expected))))
180 |
181 | ; args are backwards if from inlining
182 | (defmethod invoke-special 'cljs.core/instance?
183 | [{:keys [args] :as expr} & [expected]]
184 | (assert (= 2 (count args)) "Wrong arguments to instance?")
185 | ; are arguments the correct way round?
186 | (assert (:from-js-op expr) "instance? without inlining NYI")
187 | (binding [vs/*current-env* (:env expr)
188 | vs/*current-expr* expr]
189 | (let [target-expr (first args)
190 | inst-of-expr (second args)
191 | varsym (when (#{:var} (:op inst-of-expr))
192 | (-> inst-of-expr :name))
193 | _ (when-not varsym
194 | (err/int-error (str "First argument to instance? must be a datatype var "
195 | (:op inst-of-expr))))
196 | inst-of (c/DataType-with-unknown-params varsym)
197 | cexpr (check target-expr)
198 | expr-tr (expr-type cexpr)
199 | final-ret (ret (r/JSBoolean-maker)
200 | (fo/-FS (fo/-filter-at inst-of (ret-o expr-tr))
201 | (fo/-not-filter-at inst-of (ret-o expr-tr))))]
202 | (assoc expr
203 | expr-type final-ret))))
204 |
205 | ;=
206 | (defmethod invoke-special 'cljs.core/=
207 | [{:keys [args] :as expr} & [expected]]
208 | {:post [(vector? (:args %))
209 | (-> % u/expr-type r/TCResult?)]}
210 | (let [cargs (mapv check args)]
211 | (-> expr
212 | (update-in [:fn] check)
213 | (assoc :args cargs
214 | u/expr-type (equiv/tc-equiv := (map u/expr-type cargs) expected)))))
215 |
216 | (defmethod -check :invoke
217 | [{fexpr :fn :keys [args] :as expr} expected]
218 | (let [e (invoke-special expr)]
219 | (cond
220 | (not= e ::not-special) e
221 | :else
222 | (let [cfexpr (check fexpr)
223 | cargs (mapv check args)
224 | ftype (expr-type cfexpr)
225 | argtys (map expr-type cargs)
226 | actual (funapp/check-funapp cfexpr cargs ftype argtys expected)]
227 | (assoc expr
228 | expr-type actual)))))
229 |
230 | ;only local bindings are immutable, vars/js do not partipate in occurrence typing
231 | (defn js-var-result [expr vname expected]
232 | {:pre [((every-pred symbol? namespace) vname)
233 | ((some-fn nil? r/TCResult?) expected)]
234 | :post [(r/TCResult? %)]}
235 | (binding [vs/*current-expr* expr]
236 | (let [t (var-env/type-of vname)]
237 | (below/maybe-check-below
238 | (ret t)
239 | expected))))
240 |
241 | (defmethod -check :var
242 | [{vname :name :as expr} expected]
243 | (assoc expr expr-type
244 | (js-var-result expr vname expected)))
245 |
246 | ;(ann internal-special-form [Expr (U nil TCResult) -> Expr])
247 | (u/special-do-op spec/special-form internal-special-form)
248 |
249 | (defmethod internal-special-form ::t/tc-ignore
250 | [expr expected]
251 | (tc-ignore/check-tc-ignore check expr expected))
252 |
253 | (defn check-fn-rest [remain-dom & {:keys [rest drest kws prest]}]
254 | {:pre [(or (r/Type? rest)
255 | (r/Type? prest)
256 | (r/DottedPretype? drest)
257 | (r/KwArgs? kws))
258 | (#{1} (count (filter identity [rest drest kws prest])))]
259 | :post [(r/Type? %)]}
260 | ;(prn "rest" rest)
261 | ;(prn "drest" drest)
262 | ;(prn "kws" kws)
263 | (cond
264 | (or rest drest)
265 | (c/Un r/-nil
266 | ; only difference to Clojure impl
267 | (r/TApp-maker (r/Name-maker 'cljs.core.typed/NonEmptySeq)
268 | [(or rest (:pre-type drest))]))
269 |
270 | prest (err/nyi-error "NYI handle prest in CLJS")
271 | :else (c/KwArgs->Type kws)))
272 |
273 | (defmacro prepare-check-fn [& body]
274 | `(binding [fn-method-u/*check-fn-method1-checkfn* check
275 | fn-method-u/*check-fn-method1-rest-type* check-fn-rest]
276 | ~@body))
277 |
278 | (defmethod internal-special-form ::t/fn
279 | [{[_ _ {{fn-anns :ann} :val} :as statements] :statements fexpr :ret :as expr} expected]
280 | (prepare-check-fn
281 | (special-fn/check-special-fn check expr expected)))
282 |
283 | (defmethod internal-special-form ::t/ann-form
284 | [{[_ _ {{tsyn :type} :val} :as statements] :statements frm :ret, :keys [env], :as expr} expected]
285 | (ann-form/check-ann-form check expr expected))
286 |
287 | (defmethod internal-special-form ::t/loop
288 | [{[_ _ {{tsyns :ann} :val} :as statements] :statements frm :ret, :keys [env], :as expr} expected]
289 | (special-loop/check-special-loop check expr expected))
290 |
291 | (defmethod internal-special-form :default
292 | [expr expected]
293 | (err/int-error (str "No such internal form: " (ast-u/emit-form-fn expr))))
294 |
295 | (defmethod -check :do
296 | [expr expected]
297 | (do/check-do check-expr internal-special-form expr expected))
298 |
299 | (defmethod -check :fn
300 | [{:keys [methods] :as expr} expected]
301 | (prepare-check-fn
302 | (if expected
303 | (fn/check-fn expr expected)
304 | (special-fn/check-core-fn-no-expected check-expr expr))))
305 |
306 | (defmethod -check :set!
307 | [{:keys [target val] :as expr} expected]
308 | (set!/check-set! check-expr expr expected))
309 |
310 | (defmethod -check :if
311 | [{:keys [test then else] :as expr} expected]
312 | (if/check-if check-expr expr expected))
313 |
314 | (defmethod -check :let
315 | [expr expected]
316 | (let/check-let check-expr expr expected))
317 |
318 | (defmethod -check :letfn
319 | [{:keys [bindings body env] :as expr} expected]
320 | (letfn/check-letfn bindings body expr expected check-expr))
321 |
322 | (defmethod -check :recur
323 | [{:keys [exprs env] :as recur-expr} expected]
324 | (recur/check-recur exprs env recur-expr expected check-expr))
325 |
326 | (defmethod -check :loop
327 | [{:keys [] :as loop-expr} expected]
328 | (loop/check-loop check-expr loop-expr expected))
329 |
330 | (defmethod -check :ns
331 | [expr expected]
332 | (assoc expr
333 | expr-type (below/maybe-check-below
334 | (ret r/-any)
335 | expected)))
336 |
337 | (defmethod -check :ns*
338 | [expr expected]
339 | (assoc expr
340 | u/expr-type (below/maybe-check-below
341 | (r/ret r/-any)
342 | expected)))
343 |
344 | (defmethod -check :binding
345 | [expr expected]
346 | (binding/check-binding check-expr expr expected))
347 |
348 | (defmethod -check :quote
349 | [expr expected]
350 | (quote/check-quote check-expr constant-type/constant-type expr expected))
351 |
352 | ;; adding a bunch of missing methods:
353 |
354 | (defn fail-empty [expr]
355 | (throw (Exception. (str "Not implemented, yet: " (:op expr)))))
356 |
357 | (defmethod -check :new
358 | [{:keys [ctor args] :as expr} expected]
359 | (let [;; TODO check ctor
360 | cargs (mapv check-expr args)]
361 | (u/tc-warning (str "`new` special form is Unchecked"))
362 | (assoc :args cargs
363 | u/expr-type (below/maybe-check-below
364 | ;; TODO actual checks
365 | (r/ret (r/-unchecked))
366 | expected))))
367 |
368 | ;; TODO does this actually work?
369 | (defmethod -check :case
370 | [{:keys [test nodes default :as expr]} expected]
371 | (chk/check
372 | {:op :case
373 | :test test
374 | :default default
375 | :tests (mapcat :tests nodes)
376 | :thens (map :then nodes)}
377 | expected))
378 |
379 | (defmethod -check :case-node
380 | [expr expected]
381 | (fail-empty expr))
382 |
383 | (defmethod -check :case-test
384 | [expr expected]
385 | (fail-empty expr))
386 |
387 | (defmethod -check :case-then
388 | [expr expected]
389 | (fail-empty expr))
390 |
391 | ;TODO
392 | (defmethod -check :defrecord
393 | [expr expected]
394 | (u/tc-warning (str "`defrecord` special form is Unchecked"))
395 | (assoc expr
396 | u/expr-type (below/maybe-check-below
397 | (r/ret (r/-unchecked))
398 | expected)))
399 |
400 | (defmethod -check :deftype
401 | [expr expected]
402 | (u/tc-warning (str "`deftype` special form is Unchecked"))
403 | (assoc expr
404 | u/expr-type (below/maybe-check-below
405 | (r/ret (r/-unchecked))
406 | expected)))
407 |
408 | (defmethod -check :fn-method
409 | [expr expected]
410 | (fail-empty expr))
411 |
412 | ; see clojure.core.typed.check.dot-cljs
413 | ;; TODO check
414 | (defmethod -check :host-call
415 | [{:keys [method target args] :as expr} expected]
416 | (let [ctarget (check-expr target)
417 | cargs (mapv check-expr args)]
418 | (u/tc-warning (str "`.` special form is Unchecked"))
419 | (assoc expr
420 | :target ctarget
421 | :args cargs
422 | u/expr-type (below/maybe-check-below
423 | (r/ret (r/-unchecked))
424 | expected))))
425 |
426 | ; see clojure.core.typed.check.dot-cljs
427 | ;; TODO check
428 | (defmethod -check :host-field
429 | [{:keys [target] :as expr} expected]
430 | (let [ctarget (check-expr target)]
431 | (u/tc-warning (str "`.` special form is Unchecked"))
432 | (assoc expr
433 | :target ctarget
434 | u/expr-type (below/maybe-check-below
435 | (r/ret (r/-unchecked))
436 | expected))))
437 |
438 | ;; TODO check
439 | (defmethod -check :js-array
440 | [{:keys [items] :as expr} expected]
441 | (let [citems (mapv check-expr items)]
442 | (u/tc-warning (str "`#js []` special form is Unchecked"))
443 | (assoc expr
444 | :items citems
445 | u/expr-type (below/maybe-check-below
446 | (r/ret (r/-unchecked))
447 | expected))))
448 |
449 | (defmethod -check :js-object
450 | [{:keys [keys vals] :as expr} expected]
451 | (let [cvals (mapv check-expr vals)]
452 | (assoc expr
453 | :vals cvals
454 | u/expr-type (below/maybe-check-below
455 | (r/ret (r/JSObj-maker (zipmap (map keyword keys)
456 | (map (comp r/ret-t u/expr-type) cvals)))
457 | (fo/-true-filter))
458 | expected))))
459 |
460 | ; TODO check
461 | (defmethod -check :js-var
462 | [{:keys [name] :as expr} expected]
463 | (u/tc-warning (str "Assuming JS variable is unchecked " name))
464 | (assoc expr
465 | u/expr-type (below/maybe-check-below
466 | (r/ret (r/-unchecked))
467 | expected)))
468 |
469 | (defmethod -check :local
470 | [expr expected]
471 | (local/check-local expr expected))
472 |
473 |
474 | ; TODO check
475 | (defmethod -check :the-var
476 | [expr expected]
477 | (u/tc-warning (str "`var` special form is Unchecked"))
478 | (assoc expr
479 | u/expr-type (below/maybe-check-below
480 | (r/ret (r/-unchecked))
481 | expected)))
482 |
483 | (defmethod -check :throw
484 | [expr expected]
485 | (throw/check-throw check-expr expr expected nil))
486 |
487 | ; TODO check
488 | (defmethod -check :try
489 | [expr expected]
490 | (fail-empty expr))
491 |
492 | (defmethod -check :with-meta
493 | [expr expected]
494 | (with-meta/check-with-meta check-expr expr expected))
495 |
--------------------------------------------------------------------------------
/src/main/clojure/clojure/core/typed/base_env_cljs.clj:
--------------------------------------------------------------------------------
1 | ;; Copyright (c) Ambrose Bonnaire-Sergeant, Rich Hickey & contributors.
2 | ;; The use and distribution terms for this software are covered by the
3 | ;; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4 | ;; which can be found in the file epl-v10.html at the root of this distribution.
5 | ;; By using this software in any fashion, you are agreeing to be bound by
6 | ;; the terms of this license.
7 | ;; You must not remove this notice, or any other, from this software.
8 |
9 | (ns clojure.core.typed.base-env-cljs
10 | (:require [clojure.core.typed.base-env-helper-cljs :as h]
11 | [clojure.core.typed.base-env-common :refer [delay-and-cache-env]
12 | :as common]
13 | [clojure.core.typed.current-impl :as impl]
14 | [clojure.core.typed.bootstrap-cljs :as boot]
15 | [cljs.analyzer :as ana]
16 | [clojure.core.typed.util-cljs :as ucljs]
17 | [cljs.env :as env]
18 | [clojure.set :as set]))
19 |
20 | (ucljs/with-cljs-typed-env
21 | (ucljs/with-core-cljs-typed
22 | (binding [ana/*cljs-ns* 'cljs.core.typed]
23 | (delay-and-cache-env ^:private init-protocol-env
24 | (h/protocol-mappings
25 |
26 | cljs.core/Fn [[]]
27 | cljs.core/IFn [[]]
28 | cljs.core/ICloneable [[]]
29 | cljs.core/ICounted [[]]
30 | cljs.core/IEmptyableCollection [[]]
31 | cljs.core/ICollection [[[x :variance :covariant]]]
32 | cljs.core/IIndexed [[]]
33 | cljs.core/ASeq [[[x :variance :covariant]]]
34 | cljs.core/ISeqable [[[x :variance :covariant]]]
35 | cljs.core/ISeq [[[x :variance :covariant]]]
36 | cljs.core/INext [[[x :variance :covariant]]]
37 | cljs.core/ILookup [[[maxk :variance :covariant]
38 | [v :variance :covariant]]]
39 | cljs.core/IAssociative [[[k :variance :covariant]
40 | [v :variance :covariant]]]
41 | cljs.core/IMap [[[k :variance :covariant]
42 | [v :variance :covariant]]]
43 | cljs.core/IMapEntry [[[k :variance :covariant]
44 | [v :variance :covariant]]]
45 | cljs.core/ISet [[[x :variance :covariant]]]
46 | cljs.core/IStack [[[x :variance :covariant]]]
47 | cljs.core/IVector [[[x :variance :covariant]]]
48 | cljs.core/IDeref [[[x :variance :covariant]]]
49 | cljs.core/IDerefWithTimeout [[[x :variance :covariant]]]
50 | cljs.core/IMeta [[]]
51 | cljs.core/IWithMeta [[]]
52 | ;TODO
53 | ;cljs.core/IReduce [[]]
54 | ;cljs.core/IKVReduce [[]]
55 | cljs.core/IList [[[x :variance :covariant]]]
56 | cljs.core/IEquiv [[]]
57 | cljs.core/IHash [[]]
58 | cljs.core/ISequential [[]]
59 | cljs.core/Record [[]]
60 | cljs.core/IReversible [[[x :variance :covariant]]]
61 | cljs.core/ISorted [[]]
62 | cljs.core/IWriter [[]]
63 | cljs.core/IPrintWithWriter [[]]
64 | cljs.core/IPending [[]]
65 | ;TODO
66 | ;cljs.core/IWatchable [[]]
67 | ;cljs.core/IEditableCollection [[]]
68 | ;cljs.core/ITransientCollection [[]]
69 | ;cljs.core/ITransientAssociative [[]]
70 | ;cljs.core/ITransientMap [[]]
71 | ;cljs.core/ITransientVector [[]]
72 | ;cljs.core/ITransientSet [[]]
73 | cljs.core/IComparable [[]]
74 | ;cljs.core/IChunk [[]]
75 | ;cljs.core/IChunkedSeq [[]]
76 | ;cljs.core/IChunkedNext [[]]
77 | cljs.core/INamed [[]]
78 | cljs.core/Reduced [[[x :variance :covariant]]]
79 | ))
80 |
81 | (let [rst! (delay (impl/dynaload 'clojure.core.typed.protocol-env/reset-protocol-env!))]
82 | (defn reset-protocol-env! []
83 | (impl/with-cljs-impl
84 | (@rst! (init-protocol-env)))))
85 |
86 | #_
87 | (ann-jsclass js/Document
88 | :extends
89 | :implements
90 | :properties
91 | {getElementById [cljs.core.typed/JSString -> (U nil js/HTMLElement)]}
92 | :static-properties
93 | )
94 |
95 | (delay-and-cache-env ^:private init-jsnominals
96 | (reset-protocol-env!)
97 | (h/jsnominal-mappings
98 |
99 | ; seems like a good place to put this
100 | ;; FIXME this is actually js/String, delete
101 | string [[]
102 | :fields
103 | {}
104 | :methods
105 | {toLowerCase [-> cljs.core.typed/JSString]}]
106 |
107 | js/Document [[]
108 | :fields
109 | {}
110 | :methods
111 | {getElementById [cljs.core.typed/JSString -> (U nil js/HTMLElement)]}]
112 |
113 | js/HTMLElement [[]
114 | :fields
115 | {innerHTML cljs.core.typed/JSString
116 | tagName (U nil cljs.core.typed/JSString)}]
117 |
118 |
119 | js/Event [[]
120 | :methods
121 | {preventDefault [-> nil]}]
122 |
123 |
124 | ;http://dom.spec.whatwg.org/#interface-eventtarget
125 | js/EventTarget [[]]
126 |
127 | goog.events.Listenable [[]]
128 | goog.events.EventTarget [[]]
129 | ))
130 |
131 | (let [rst! (delay (impl/dynaload 'clojure.core.typed.jsnominal-env/reset-jsnominal!))]
132 | (defn reset-jsnominal-env! []
133 | (impl/with-cljs-impl
134 | (@rst! (init-jsnominals)))))
135 |
136 | ;;; vars specific to cljs
137 | (delay-and-cache-env ^:private init-var-env
138 | (reset-protocol-env!)
139 | (reset-jsnominal-env!)
140 | (merge
141 | (common/parse-cljs-ann-map @common/common-var-annotations)
142 | (h/var-mappings
143 |
144 | ;internal vars
145 | cljs.core.typed/ann* [Any Any -> Any]
146 | cljs.core.typed/ann-protocol* [Any Any Any -> Any]
147 | cljs.core.typed/ann-datatype* [Any Any Any Any -> Any]
148 | cljs.core.typed/def-alias* [Any Any -> Any]
149 | cljs.core.typed/typed-deps* [Any -> Any]
150 | cljs.core.typed/ann-jsnominal* [Any Any -> Any]
151 |
152 | cljs.core/+ (IFn [cljs.core.typed/CLJSInteger * -> cljs.core.typed/CLJSInteger]
153 | [cljs.core.typed/JSNumber * -> cljs.core.typed/JSNumber])
154 | cljs.core/- (IFn [cljs.core.typed/CLJSInteger * -> cljs.core.typed/CLJSInteger]
155 | [cljs.core.typed/JSNumber * -> cljs.core.typed/JSNumber])
156 | cljs.core/* (IFn [cljs.core.typed/CLJSInteger * -> cljs.core.typed/CLJSInteger]
157 | [cljs.core.typed/JSNumber * -> cljs.core.typed/JSNumber])
158 | cljs.core/nth (All [x y]
159 | (IFn [(U nil (cljs.core/ISeqable x)) cljs.core.typed/CLJSInteger -> x]
160 | [(U nil (cljs.core/ISeqable x)) cljs.core.typed/CLJSInteger y -> (U y x)]))
161 |
162 | cljs.core/*flush-on-newline* cljs.core.typed/JSBoolean
163 | cljs.core/*print-newline* cljs.core.typed/JSBoolean
164 | cljs.core/*print-readably* cljs.core.typed/JSBoolean
165 | cljs.core/*print-meta* cljs.core.typed/JSBoolean
166 | cljs.core/*print-dup* cljs.core.typed/JSBoolean
167 | cljs.core/*print-length* (U nil cljs.core.typed/CLJSInteger)
168 |
169 | cljs.core/enable-console-print! [-> Any]
170 |
171 | cljs.core/truth_ [Any -> Any]
172 |
173 | cljs.core/coercive-= [Any Any -> cljs.core.typed/JSBoolean]
174 |
175 | cljs.core/nil? (Pred nil)
176 | cljs.core/undefined? (Pred JSUndefined)
177 |
178 | cljs.core/array? (ReadOnlyArray Any)
179 |
180 | cljs.core/object? [Any -> cljs.core.typed/JSBoolean]
181 |
182 | cljs.core/native-satisfies? [Any Any -> Any]
183 |
184 | cljs.core/is_proto_ [Any -> Any]
185 |
186 | cljs.core/*main-cli-fn* (U nil [Any * -> Any])
187 |
188 | cljs.core/missing-protocol [Any Any -> Any]
189 | cljs.core/type->str [Any -> cljs.core.typed/JSString]
190 |
191 | cljs.core/make-array (All [r]
192 | (IFn [cljs.core.typed/CLJSInteger -> (Array r)]
193 | [Any cljs.core.typed/CLJSInteger -> (Array r)]))
194 |
195 | cljs.core/array (All [r]
196 | [r * -> (Array r)])
197 |
198 | cljs.core/alength [(ReadOnlyArray Any) -> cljs.core.typed/CLJSInteger]
199 |
200 | cljs.core/into-array (All [x]
201 | (IFn [(U nil (cljs.core/ISeqable x)) -> (Array x)]
202 | [Any (U nil (cljs.core/ISeqable x)) -> (Array x)]))
203 |
204 | cljs.core/pr-str* [Any -> cljs.core.typed/JSString]
205 |
206 | cljs.core/clone [Any -> Any]
207 |
208 | cljs.core/cloneable? (Pred cljs.core/ICloneable)
209 |
210 |
211 | cljs.core/count
212 | ; TODO also accepts Counted
213 | ; FIXME should return integer
214 | [(U nil (cljs.core/ISeqable Any)) -> cljs.core.typed/CLJSInteger :object {:id 0, :path [Count]}]
215 | cljs.core/prim-seq
216 | (All [x]
217 | [(cljs.core/ISeqable x) -> (U nil (cljs.core/ISeq x))])
218 |
219 | cljs.core/key-test [Keyword Any -> cljs.core.typed/JSBoolean]
220 |
221 | cljs.core/fn? [Any -> cljs.core.typed/JSBoolean]
222 | cljs.core/ifn? [Any -> cljs.core.typed/JSBoolean]
223 |
224 | ;;pop needs to be defined here because
225 | ;;definition of List differs between clj and cljs
226 | cljs.core/pop (All [x]
227 | (IFn
228 | [(IList x) -> (IList x)]
229 | [(Vec x) -> (Vec x)]
230 | [(Stack x) -> (Stack x)]))
231 |
232 | cljs.core/clj->js [Any -> Any]
233 | cljs.core/js->clj [Any -> Any]
234 | cljs.core/js-obj [Any * -> Any]
235 |
236 | ;;pseudo-private vars
237 | cljs.core/-conj [Any Any -> Any]
238 | ;cljs.core.List.Empty (IList Any)
239 | )))
240 |
241 | (delay-and-cache-env ^:private init-var-nochecks
242 | (set (keys (init-var-env))))
243 |
244 | (delay-and-cache-env init-jsvar-env
245 | (reset-protocol-env!)
246 | (reset-jsnominal-env!)
247 | (h/js-var-mappings
248 | ;; js
249 |
250 | js/document js/Document
251 |
252 | ;; goog.dom
253 |
254 | goog.dom/setTextContent [js/Element (U cljs.core.typed/JSString cljs.core.typed/JSNumber) -> js/Window]
255 | goog.dom/getElementsByTagNameAndClass
256 | [(U nil cljs.core.typed/JSString) (U nil cljs.core.typed/JSString) (U nil js/Document js/Element) -> (cljs.core/ISeqable js/Element)]
257 | goog.dom.classes/set [(U js/Node nil) cljs.core.typed/JSString -> Any]
258 | goog.dom.classes/add [(U js/Node nil) (U nil cljs.core.typed/JSString) * -> cljs.core.typed/JSBoolean]
259 | goog.dom.classes/remove [(U js/Node nil) (U nil cljs.core.typed/JSString) * -> cljs.core.typed/JSBoolean]
260 | goog.style/getPageOffsetLeft [(U nil js/Element) -> cljs.core.typed/JSNumber]
261 | goog.style/getPageOffsetTop [(U nil js/Element) -> cljs.core.typed/JSNumber]
262 | goog.events/listen [(U nil js/EventTarget goog.events.EventTarget goog.events.Listenable)
263 | (U nil cljs.core.typed/JSString (ReadOnlyArray cljs.core.typed/JSString)) -> cljs.core.typed/JSNumber]
264 |
265 | goog.events.EventType.KEYUP cljs.core.typed/JSString
266 | goog.events.EventType.KEYDOWN cljs.core.typed/JSString
267 | goog.events.EventType.KEYPRESS cljs.core.typed/JSString
268 | goog.events.EventType.CLICK cljs.core.typed/JSString
269 | goog.events.EventType.DBLCLICK cljs.core.typed/JSString
270 | goog.events.EventType.MOUSEOVER cljs.core.typed/JSString
271 | goog.events.EventType.MOUSEOUT cljs.core.typed/JSString
272 | goog.events.EventType.MOUSEMOVE cljs.core.typed/JSString
273 | ))
274 |
275 | (delay-and-cache-env init-alias-env
276 | (reset-protocol-env!)
277 | (reset-jsnominal-env!)
278 | (h/alias-mappings
279 | ^{:doc "A type that returns true for cljs.core/integer?"}
280 | cljs.core.typed/AnyInteger cljs.core.typed/CLJSInteger
281 |
282 | ^{:doc "A type that returns true for cljs.core/integer?"}
283 | cljs.core.typed/Integer cljs.core.typed/CLJSInteger
284 |
285 | ^{:doc "A type that returns true for cljs.core/integer?"}
286 | cljs.core.typed/Int cljs.core.typed/CLJSInteger
287 |
288 | ^{:doc "A type that returns true for cljs.core/number?"}
289 | cljs.core.typed/Number cljs.core.typed/JSNumber
290 |
291 | ^{:doc "A type that returns true for cljs.core/number?"}
292 | cljs.core.typed/Num cljs.core.typed/JSNumber
293 |
294 | ^{:doc "A type that returns true for cljs.core/string?"}
295 | cljs.core.typed/String cljs.core.typed/JSString
296 |
297 | ^{:doc "A type that returns true for cljs.core/string?"}
298 | cljs.core.typed/Str cljs.core.typed/JSString
299 |
300 | ^{:doc "A type that returns true for cljs.core/boolean?"}
301 | cljs.core.typed/Boolean cljs.core.typed/JSBoolean
302 |
303 | ^{:doc "vector -- alias for common anns"}
304 | cljs.core.typed/Vec (TFn [[x :variance :covariant]]
305 | (IVector x))
306 |
307 | ^{:doc "vector -- alias for common anns"}
308 | cljs.core.typed/IPersistentVector (TFn [[x :variance :covariant]]
309 | (IVector x))
310 |
311 | ^{:doc "map -- alias for common anns"}
312 | cljs.core.typed/Map (TFn [[k :variance :covariant]
313 | [v :variance :covariant]]
314 | (IMap k v))
315 |
316 | ^{:doc "map -- alias for common anns"}
317 | cljs.core.typed/IPersistentMap (TFn [[k :variance :covariant]
318 | [v :variance :covariant]]
319 | (IMap k v))
320 |
321 | ^{:doc "map -- alias for common anns"}
322 | cljs.core.typed/APersistentMap (TFn [[k :variance :covariant]
323 | [v :variance :covariant]]
324 | (IMap k v))
325 |
326 | ^{:doc "associative -- alias for common anns"}
327 | cljs.core.typed/Associative IAssociative
328 |
329 | ^{:doc "An atom that can read and write type x."
330 | :forms [(Atom1 t)]}
331 | cljs.core.typed/Atom1 (TFn [[x :variance :invariant]]
332 | (cljs.core/Atom x x))
333 | ^{:doc "An atom that can write type w and read type r."
334 | :forms [(Atom2 t)]}
335 | cljs.core.typed/Atom2 (TFn [[w :variance :contravariant]
336 | [r :variance :covariant]]
337 | (cljs.core/Atom w r))
338 |
339 | ^{:doc "sequential -- alias for common anns"}
340 | cljs.core.typed/Sequential ISequential
341 |
342 | ^{:doc "set -- alias for common anns"}
343 | cljs.core.typed/Set ISet
344 |
345 | ^{:doc "set -- alias for common anns"}
346 | cljs.core.typed/IPersistentSet ISet
347 |
348 |
349 | ^{:doc "A type that can be used to create a sequence of member type x."}
350 | cljs.core.typed/Seqable (TFn [[x :variance :covariant]]
351 | (cljs.core/ISeqable x))
352 |
353 | ^{:doc "A persistent sequence of member type x."
354 | :forms [(Seq t)]}
355 | cljs.core.typed/Seq (TFn [[x :variance :covariant]]
356 | (cljs.core/ISeq x))
357 |
358 | ^{:doc "A persistent sequence of member type x with count greater than 0."
359 | :forms [(NonEmptySeq t)]}
360 | cljs.core.typed/NonEmptySeq (TFn [[x :variance :covariant]]
361 | (I (cljs.core/ISeq x) (CountRange 1)))
362 |
363 |
364 |
365 |
366 | ;;copied from impl/init-aliases
367 |
368 | ;;Seqables
369 | ^{:doc "A type that can be used to create a sequence of member type x
370 | with count 0."
371 | :forms [(EmptySeqable t)]}
372 | cljs.core.typed/EmptySeqable (TFn [[x :variance :covariant]]
373 | (I (cljs.core.typed/Seqable x) (ExactCount 0)))
374 |
375 | ^{:doc "A type that can be used to create a sequence of member type x
376 | with count greater than 0."
377 | :forms [(NonEmptySeqable t)]}
378 | cljs.core.typed/NonEmptySeqable
379 | (TFn [[x :variance :covariant]]
380 | (I (cljs.core.typed/Seqable x) (CountRange 1)))
381 |
382 | ;;Option
383 | ^{:doc "A union of x and nil."
384 | :forms [(Option t)]}
385 | cljs.core.typed/Option (TFn [[x :variance :covariant]] (U nil x))
386 |
387 |
388 | ^{:doc "A persistent collection with member type x."
389 | :forms [(Coll t)]}
390 | cljs.core.typed/Coll (TFn [[x :variance :covariant]]
391 | (cljs.core/ICollection x))
392 |
393 | ^{:doc "A persistent collection with member type x and count greater than 0."
394 | :forms [(NonEmptyColl t)]}
395 | cljs.core.typed/NonEmptyColl (TFn [[x :variance :covariant]]
396 | (I (cljs.core/ICollection x)
397 | (CountRange 1)))
398 |
399 | ^{:doc "A sequential non-empty seq retured from clojure.core/seq"
400 | :forms [(NonEmptyASeq t)]}
401 | cljs.core.typed/NonEmptyASeq
402 | (TFn [[x :variance :covariant]]
403 | (I (cljs.core/ASeq x)
404 | (cljs.core/ISeq x)
405 | (cljs.core/ISeqable x)
406 | cljs.core/ISequential
407 | ;(Iterable x)
408 | (cljs.core/ICollection x)
409 | (cljs.core/IList x)
410 | ;clojure.lang.IObj
411 | (CountRange 1)))
412 |
413 |
414 | ^{:doc "The type of all things with count 0. Use as part of an intersection.
415 | eg. See EmptySeqable."
416 | :forms [EmptyCount]}
417 | cljs.core.typed/EmptyCount (ExactCount 0)
418 |
419 | ^{:doc "The type of all things with count greater than 0. Use as part of an intersection.
420 | eg. See NonEmptySeq"
421 | :forms [NonEmptyCount]}
422 | cljs.core.typed/NonEmptyCount (CountRange 1)
423 |
424 | ^{:doc "A union of x and nil."
425 | :forms [(Nilable t)]}
426 | cljs.core.typed/Nilable (TFn [[x :variance :covariant]] (U nil x))
427 |
428 | ^{:doc "A persistent vector returned from clojure.core/vector (and others)"
429 | :forms [(AVec t)]}
430 | cljs.core.typed/AVec (TFn [[x :variance :covariant]]
431 | (I (IPersistentVector x)
432 | ;(java.lang.Iterable x)
433 | (ICollection x)
434 | (IList x)
435 | ;clojure.lang.IObj
436 | ))
437 |
438 | ^{:doc "A persistent vector returned from clojure.core/vector (and others) and count greater than 0."
439 | :forms [(NonEmptyAVec t)]}
440 | cljs.core.typed/NonEmptyAVec (TFn [[x :variance :covariant]]
441 | (I (IPersistentVector x)
442 | ;(java.lang.Iterable x)
443 | (ICollection x)
444 | (IList x)
445 | ;clojure.lang.IObj
446 | (CountRange 1)))
447 |
448 | ^{:doc "The result of clojure.core/seq."
449 | :forms [(NilableNonEmptyASeq t)]}
450 | cljs.core.typed/NilableNonEmptyASeq
451 | (TFn [[x :variance :covariant]]
452 | (U nil
453 | (I (cljs.core/ASeq x)
454 | (cljs.core/ISeq x)
455 | cljs.core/ISequential
456 | ;(Iterable x)
457 | (cljs.core/ICollection x)
458 | (cljs.core/IList x)
459 | ;clojure.lang.IObj
460 | (CountRange 1))))
461 |
462 | ^{:doc "A Clojure persistent list."
463 | :forms [(PersistentList t)]}
464 | cljs.core.typed/PersistentList
465 | (TFn [[x :variance :covariant]]
466 | (cljs.core/IList x))
467 |
468 | ^{:doc "Collection"}
469 | cljs.core.typed/Collection
470 | (TFn [[x :variance :covariant]]
471 | (cljs.core/ICollection x))
472 |
473 | ^{:doc "A Clojure stack."
474 | :forms [(Stack t)]}
475 | cljs.core.typed/Stack
476 | (TFn [[x :variance :covariant]]
477 | (cljs.core/IStack x))
478 |
479 | ^{:doc "Reversible maps to IReversible"
480 | :forms [(Reversible t)]}
481 | cljs.core.typed/Reversible
482 | (TFn [[x :variance :covariant]]
483 | (cljs.core/IReversible x))))
484 |
485 |
486 | (let [rst! (delay (impl/dynaload 'clojure.core.typed.name-env/reset-name-env!))]
487 | (defn reset-alias-env! []
488 | (let [alias-env (init-alias-env)]
489 | ; Ensure init-alias-env agrees with the -base-aliases
490 | (assert (= (set (keys alias-env))
491 | (set (map #(symbol "cljs.core.typed" (str %))
492 | boot/-base-aliases)))
493 | (str "core.typed Bug! Base aliases do not agree with base environment."
494 | " Missing from cljs.core.typed ns: "
495 | (set/difference (set (keys alias-env))
496 | (set (map #(symbol "cljs.core.typed" (str %))
497 | boot/-base-aliases)))
498 | " Missing from base-env-cljs ns "
499 | (set/difference (set (map #(symbol "cljs.core.typed" (str %))
500 | boot/-base-aliases))
501 | (set (keys alias-env)))))
502 | (@rst! alias-env))))
503 |
504 | (delay-and-cache-env init-declared-kinds {})
505 |
506 | (delay-and-cache-env init-datatype-env
507 | (reset-protocol-env!)
508 | (reset-jsnominal-env!)
509 | (h/datatype-mappings
510 |
511 | cljs.core/Atom [[[w :variance :contravariant]
512 | [r :variance :covariant]]]
513 | cljs.core/Symbol [[]]
514 | cljs.core/Keyword [[]]
515 | cljs.core/List [[[a :variance :covariant]]]
516 | cljs.core/Reduced [[[x :variance :covariant]]]
517 | ))
518 | )
519 |
520 | (let [reset-var-type-env! (delay (impl/dynaload 'clojure.core.typed.var-env/reset-var-type-env!))
521 | reset-jsvar-type-env! (delay (impl/dynaload 'clojure.core.typed.var-env/reset-jsvar-type-env!))
522 | reset-declared-kinds! (delay (impl/dynaload 'clojure.core.typed.declared-kind-env/reset-declared-kinds!))
523 | reset-datatype-env! (delay (impl/dynaload 'clojure.core.typed.datatype-env/reset-datatype-env!))]
524 | (defn reset-cljs-envs! []
525 | (ucljs/with-cljs-typed-env
526 | (impl/with-cljs-impl
527 | (reset-alias-env!)
528 | (@reset-var-type-env! (init-var-env) (init-var-nochecks))
529 | (@reset-jsvar-type-env! (init-jsvar-env))
530 | (reset-protocol-env!)
531 | (@reset-declared-kinds! (init-declared-kinds))
532 | (reset-jsnominal-env!)
533 | (@reset-datatype-env! (init-datatype-env))))
534 | nil))))
535 |
--------------------------------------------------------------------------------