diff --git a/src/main/cljs/cljs/js.cljs b/src/main/cljs/cljs/js.cljs index 4e29fd7e84..ed2711b2a5 100644 --- a/src/main/cljs/cljs/js.cljs +++ b/src/main/cljs/cljs/js.cljs @@ -39,11 +39,25 @@ 0 (- (count file) 5))] (symbol (demunge lib-name)))) +(defn- drop-macros-suffix + [ns-name] + (if (string/ends-with? ns-name "$macros") + (subs ns-name 0 (- (count ns-name) 7)) + ns-name)) + +(defn- elide-macros-suffix + [sym] + (symbol (drop-macros-suffix (namespace sym)) (name sym))) + (defn- resolve-symbol [sym] (if (string/starts-with? (str sym) ".") sym - (ana/resolve-symbol sym))) + (elide-macros-suffix (ana/resolve-symbol sym)))) + +(defn- read [eof rdr] + (binding [*ns* (symbol (drop-macros-suffix (str *ns*)))] + (r/read {:eof eof :read-cond :allow :features #{:cljs}} rdr))) (defn- atom? [x] (instance? Atom x)) @@ -528,7 +542,7 @@ comp/*source-map-data* (:*sm-data* bound-vars) ana/*cljs-file* (:cljs-file opts)] (let [res (try - {:value (r/read {:eof eof :read-cond :allow :features #{:cljs}} rdr)} + {:value (read eof rdr)} (catch :default cause (wrap-error (ana/error aenv @@ -692,7 +706,7 @@ r/resolve-symbol resolve-symbol comp/*source-map-data* (:*sm-data* bound-vars)] (let [res (try - {:value (r/read {:eof eof :read-cond :allow :features #{:cljs}} rdr)} + {:value (read eof rdr)} (catch :default cause (wrap-error (ana/error aenv @@ -792,7 +806,7 @@ comp/*source-map-data* (:*sm-data* bound-vars) ana/*cljs-file* (:cljs-file opts)] (let [res (try - {:value (r/read {:eof eof :read-cond :allow :features #{:cljs}} rdr)} + {:value (read eof rdr)} (catch :default cause (wrap-error (ana/error aenv diff --git a/src/main/cljs/cljs/spec.cljc b/src/main/cljs/cljs/spec.cljc index bda8df39ab..44520aaca3 100644 --- a/src/main/cljs/cljs/spec.cljc +++ b/src/main/cljs/cljs/spec.cljc @@ -57,7 +57,7 @@ (let [k (if (symbol? k) (ns-qualify &env k) k) form (res &env spec-form)] (swap! registry-ref assoc k form) - `(cljs.spec/def-impl '~k '~form ~spec-form))) + `(def-impl '~k '~form ~spec-form))) (defmacro spec "Takes a single predicate form, e.g. can be the name of a predicate, @@ -76,7 +76,7 @@ Returns a spec." [form & {:keys [gen]}] (when form - `(cljs.spec/spec-impl '~(res &env form) ~form ~gen nil))) + `(spec-impl '~(res &env form) ~form ~gen nil))) (defmacro multi-spec "Takes the name of a spec/predicate-returning multimethod and a @@ -105,7 +105,7 @@ though those values are not evident in the spec. " [mm retag] - `(cljs.spec/multi-spec-impl '~(res &env mm) (var ~mm) ~retag)) + `(multi-spec-impl '~(res &env mm) (var ~mm) ~retag)) (defmacro keys "Creates and returns a map validating spec. :req and :opt are both @@ -160,12 +160,12 @@ pred-exprs (into pred-exprs (parse-req req-un unk)) pred-forms (walk/postwalk #(res &env %) pred-exprs)] ;; `(map-spec-impl ~req-keys '~req ~opt '~pred-forms ~pred-exprs ~gen) - `(cljs.spec/map-spec-impl {:req '~req :opt '~opt :req-un '~req-un :opt-un '~opt-un - :req-keys '~req-keys :req-specs '~req-specs - :opt-keys '~opt-keys :opt-specs '~opt-specs - :pred-forms '~pred-forms - :pred-exprs ~pred-exprs - :gfn ~gen}))) + `(map-spec-impl {:req '~req :opt '~opt :req-un '~req-un :opt-un '~opt-un + :req-keys '~req-keys :req-specs '~req-specs + :opt-keys '~opt-keys :opt-specs '~opt-specs + :pred-forms '~pred-forms + :pred-exprs ~pred-exprs + :gfn ~gen}))) (defmacro or "Takes key+pred pairs, e.g. @@ -182,7 +182,7 @@ pred-forms (mapv second pairs) pf (mapv #(res &env %) pred-forms)] (clojure.core/assert (clojure.core/and (even? (count key-pred-forms)) (every? keyword? keys)) "spec/or expects k1 p1 k2 p2..., where ks are keywords") - `(cljs.spec/or-spec-impl ~keys '~pf ~pred-forms nil))) + `(or-spec-impl ~keys '~pf ~pred-forms nil))) (defmacro and "Takes predicate/spec-forms, e.g. @@ -192,7 +192,7 @@ Returns a spec that returns the conformed value. Successive conformed values propagate through rest of predicates." [& pred-forms] - `(cljs.spec/and-spec-impl '~(mapv #(res &env %) pred-forms) ~(vec pred-forms) nil)) + `(and-spec-impl '~(mapv #(res &env %) pred-forms) ~(vec pred-forms) nil)) (defmacro every "takes a pred and validates collection elements against that pred. @@ -224,8 +224,8 @@ See also - coll-of, every-kv " [pred & {:keys [into kind count max-count min-count distinct gen-max gen-into gen] :as opts}] - (let [nopts (-> opts (dissoc :gen) (assoc :cljs.spec/kind-form `'~(res &env (:kind opts))))] - `(cljs.spec/every-impl '~pred ~pred ~nopts ~gen))) + (let [nopts (-> opts (dissoc :gen) (assoc ::kind-form `'~(res &env (:kind opts))))] + `(every-impl '~pred ~pred ~nopts ~gen))) (defmacro every-kv "like 'every' but takes separate key and val preds and works on associative collections. @@ -235,7 +235,7 @@ See also - map-of" [kpred vpred & opts] - `(every (tuple ~kpred ~vpred) :cljs.spec/kfn (fn [i# v#] (nth v# 0)) :into {} ~@opts)) + `(every (tuple ~kpred ~vpred) ::kfn (fn [i# v#] (nth v# 0)) :into {} ~@opts)) (defmacro coll-of "Returns a spec for a collection of items satisfying pred. Unlike @@ -249,7 +249,7 @@ See also - every, map-of" [pred & opts] - `(every ~pred :cljs.spec/conform-all true ~@opts)) + `(every ~pred ::conform-all true ~@opts)) (defmacro map-of "Returns a spec for a map whose keys satisfy kpred and vals satisfy @@ -262,25 +262,25 @@ See also - every-kv" [kpred vpred & opts] - `(every-kv ~kpred ~vpred :cljs.spec/conform-all true :kind map? ~@opts)) + `(every-kv ~kpred ~vpred ::conform-all true :kind map? ~@opts)) (defmacro * "Returns a regex op that matches zero or more values matching pred. Produces a vector of matches iff there is at least one match" [pred-form] - `(cljs.spec/rep-impl '~(res &env pred-form) ~pred-form)) + `(rep-impl '~(res &env pred-form) ~pred-form)) (defmacro + "Returns a regex op that matches one or more values matching pred. Produces a vector of matches" [pred-form] - `(cljs.spec/rep+impl '~(res &env pred-form) ~pred-form)) + `(rep+impl '~(res &env pred-form) ~pred-form)) (defmacro ? "Returns a regex op that matches zero or one value matching pred. Produces a single value (not a collection) if matched." [pred-form] - `(cljs.spec/maybe-impl ~pred-form '~pred-form)) + `(maybe-impl ~pred-form '~pred-form)) (defmacro alt "Takes key+pred pairs, e.g. @@ -297,7 +297,7 @@ pred-forms (mapv second pairs) pf (mapv #(res &env %) pred-forms)] (clojure.core/assert (clojure.core/and (even? (count key-pred-forms)) (every? keyword? keys)) "alt expects k1 p1 k2 p2..., where ks are keywords") - `(cljs.spec/alt-impl ~keys ~pred-forms '~pf))) + `(alt-impl ~keys ~pred-forms '~pf))) (defmacro cat "Takes key+pred pairs, e.g. @@ -313,7 +313,7 @@ pf (mapv #(res &env %) pred-forms)] ;;(prn key-pred-forms) (clojure.core/assert (clojure.core/and (even? (count key-pred-forms)) (every? keyword? keys)) "cat expects k1 p1 k2 p2..., where ks are keywords") - `(cljs.spec/cat-impl ~keys ~pred-forms '~pf))) + `(cat-impl ~keys ~pred-forms '~pf))) (defmacro & "takes a regex op re, and predicates. Returns a regex-op that consumes @@ -321,15 +321,15 @@ conjunction of the predicates, and any conforming they might perform." [re & preds] (let [pv (vec preds)] - `(cljs.spec/amp-impl ~re ~pv '~(mapv #(res &env %) pv)))) + `(amp-impl ~re ~pv '~(mapv #(res &env %) pv)))) (defmacro conformer "takes a predicate function with the semantics of conform i.e. it should return either a (possibly converted) value or :cljs.spec/invalid, and returns a spec that uses it as a predicate/conformer. Optionally takes a second fn that does unform of result of first" - ([f] `(cljs.spec/spec-impl '~f ~f nil true)) - ([f unf] `(cljs.spec/spec-impl '~f ~f nil true ~unf))) + ([f] `(spec-impl '~f ~f nil true)) + ([f unf] `(spec-impl '~f ~f nil true ~unf))) (defmacro fspec "takes :args :ret and (optional) :fn kwargs whose values are preds @@ -347,7 +347,7 @@ that returns a test.check generator." [& {:keys [args ret fn gen]}] (let [env &env] - `(cljs.spec/fspec-impl (spec ~args) '~(res env args) + `(fspec-impl (spec ~args) '~(res env args) (spec ~ret) '~(res env ret) (spec ~fn) '~(res env fn) ~gen))) @@ -357,7 +357,7 @@ will be referred to in paths using its ordinal." [& preds] (clojure.core/assert (not (empty? preds))) - `(cljs.spec/tuple-impl '~(mapv #(res &env %) preds) ~(vec preds))) + `(tuple-impl '~(mapv #(res &env %) preds) ~(vec preds))) (def ^:private _speced_vars (atom #{})) @@ -398,7 +398,7 @@ :ret symbol?)" [fn-sym & specs] (swap! _speced_vars conj (ns-qualify &env fn-sym)) - `(cljs.spec/def ~fn-sym (cljs.spec/fspec ~@specs))) + `(cljs.spec/def ~fn-sym (fspec ~@specs))) (defmacro keys* "takes the same arguments as spec/keys and returns a regex op that matches sequences of key/values, @@ -416,13 +416,13 @@ {:i1 42, :m {:a 1, :c 2, :d 4}, :i2 99}" [& kspecs] `(let [mspec# (keys ~@kspecs)] - (cljs.spec/with-gen (cljs.spec/& (* (cat :cljs.spec/k keyword? :cljs.spec/v cljs.core/any?)) :cljs.spec/kvs->map mspec#) - (fn [] (gen/fmap (fn [m#] (apply concat m#)) (cljs.spec/gen mspec#)))))) + (with-gen (& (* (cat ::k keyword? ::v cljs.core/any?)) ::kvs->map mspec#) + (fn [] (gen/fmap (fn [m#] (apply concat m#)) (gen mspec#)))))) (defmacro nilable "returns a spec that accepts nil and values satisfiying pred" [pred] - `(and (or :cljs.spec/nil nil? :cljs.spec/pred ~pred) (conformer second))) + `(and (or ::nil nil? ::pred ~pred) (conformer second))) (defmacro inst-in "Returns a spec that validates insts in the range from start @@ -431,7 +431,7 @@ `(let [st# (cljs.core/inst-ms ~start) et# (cljs.core/inst-ms ~end) mkdate# (fn [d#] (js/Date. d#))] - (spec (and cljs.core/inst? #(cljs.spec/inst-in-range? ~start ~end %)) + (spec (and cljs.core/inst? #(inst-in-range? ~start ~end %)) :gen (fn [] (gen/fmap mkdate# (gen/large-integer* {:min st# :max et#})))))) @@ -440,7 +440,7 @@ "Returns a spec that validates longs in the range from start (inclusive) to end (exclusive)." [start end] - `(spec (and c/int? #(cljs.spec/int-in-range? ~start ~end %)) + `(spec (and c/int? #(int-in-range? ~start ~end %)) :gen #(gen/large-integer* {:min ~start :max (dec ~end)}))) (defmacro merge @@ -450,7 +450,7 @@ predicates. Unlike 'and', merge can generate maps satisfying the union of the predicates." [& pred-forms] - `(cljs.spec/merge-spec-impl '~(mapv #(res &env %) pred-forms) ~(vec pred-forms) nil)) + `(merge-spec-impl '~(mapv #(res &env %) pred-forms) ~(vec pred-forms) nil)) (defmacro exercise-fn "exercises the fn named by sym (a symbol) by applying it to @@ -467,10 +467,10 @@ (= (first sym) 'quote)) second)] `(let [fspec# ~(if-not fspec - `(cljs.spec/get-spec '~(:name (resolve &env sym))) + `(get-spec '~(:name (resolve &env sym))) fspec) f# ~sym] - (for [args# (gen/sample (cljs.spec/gen (:args fspec#)) ~n)] + (for [args# (gen/sample (gen (:args fspec#)) ~n)] [args# (apply f# args#)]))))) (defmacro ^:private init-compile-asserts [] @@ -489,8 +489,8 @@ If (check-asserts?) is false at runtime, always returns x. Defaults to value of 'cljs.spec/*runtime-asserts*', or false if not set. You can toggle check-asserts? with (check-asserts bool)." [spec x] - `(if cljs.spec/*compile-asserts* - (if cljs.spec/*runtime-asserts* - (cljs.spec/assert* ~spec ~x) + `(if *compile-asserts* + (if *runtime-asserts* + (assert* ~spec ~x) ~x) ~x)) diff --git a/src/main/cljs/cljs/spec/impl/gen.cljc b/src/main/cljs/cljs/spec/impl/gen.cljc index 9200a0bf3a..98bab2cb92 100644 --- a/src/main/cljs/cljs/spec/impl/gen.cljc +++ b/src/main/cljs/cljs/spec/impl/gen.cljc @@ -34,7 +34,7 @@ generator that delegates to that, but delays creation until used." [& body] - `(cljs.spec.impl.gen/delay-impl (c/delay ~@body))) + `(delay-impl (c/delay ~@body))) (defmacro ^:skip-wiki lazy-combinator "Implementation macro, do not call directly." diff --git a/src/main/cljs/cljs/spec/test.cljc b/src/main/cljs/cljs/spec/test.cljc index ac6ae5ffe1..3957c1f9ba 100644 --- a/src/main/cljs/cljs/spec/test.cljc +++ b/src/main/cljs/cljs/spec/test.cljc @@ -43,7 +43,7 @@ returns the set of all symbols naming vars in those nses." (defmacro with-instrument-disabled "Disables instrument's checking of calls, within a scope." [& body] - `(binding [cljs.spec.test/*instrument-enabled* nil] + `(binding [*instrument-enabled* nil] ~@body)) (defmacro instrument-1 @@ -51,7 +51,7 @@ returns the set of all symbols naming vars in those nses." (let [v (ana-api/resolve &env s)] (when v (swap! instrumented-vars conj (:name v)) - `(let [checked# (cljs.spec.test/instrument-1* ~s (var ~s) ~opts)] + `(let [checked# (instrument-1* ~s (var ~s) ~opts)] (when checked# (set! ~s checked#)) '~(:name v))))) @@ -60,7 +60,7 @@ returns the set of all symbols naming vars in those nses." (let [v (ana-api/resolve &env s)] (when v (swap! instrumented-vars disj (:name v)) - `(let [raw# (cljs.spec.test/unstrument-1* ~s (var ~s))] + `(let [raw# (unstrument-1* ~s (var ~s))] (when raw# (set! ~s raw#)) '~(:name v))))) diff --git a/src/main/cljs/cljs/test.cljc b/src/main/cljs/cljs/test.cljc index 377a83eb93..725c7570cf 100644 --- a/src/main/cljs/cljs/test.cljc +++ b/src/main/cljs/cljs/test.cljc @@ -34,10 +34,10 @@ `(let [values# (list ~@args) result# (apply ~pred values#)] (if result# - (cljs.test/do-report + (do-report {:type :pass, :message ~msg, :expected '~form, :actual (cons ~pred values#)}) - (cljs.test/do-report + (do-report {:type :fail, :message ~msg, :expected '~form, :actual (list '~'not (cons '~pred values#))})) result#))) @@ -48,10 +48,10 @@ [msg form] `(let [value# ~form] (if value# - (cljs.test/do-report + (do-report {:type :pass, :message ~msg, :expected '~form, :actual value#}) - (cljs.test/do-report + (do-report {:type :fail, :message ~msg, :expected '~form, :actual value#})) value#)) @@ -72,7 +72,7 @@ (defmethod assert-expr :always-fail [menv msg form] ;; nil test: always fail - `(cljs.test/do-report {:type :fail, :message ~msg})) + `(do-report {:type :fail, :message ~msg})) (defmethod assert-expr :default [menv msg form] (if (and (sequential? form) @@ -86,10 +86,10 @@ object# ~(nth form 2)] (let [result# (instance? klass# object#)] (if result# - (cljs.test/do-report + (do-report {:type :pass, :message ~msg, :expected '~form, :actual (type object#)}) - (cljs.test/do-report + (do-report {:type :fail, :message ~msg, :expected '~form, :actual (type object#)})) result#))) @@ -102,11 +102,11 @@ body (nthnext form 2)] `(try ~@body - (cljs.test/do-report + (do-report {:type :fail, :message ~msg, :expected '~form, :actual nil}) (catch ~klass e# - (cljs.test/do-report + (do-report {:type :pass, :message ~msg, :expected '~form, :actual e#}) e#)))) @@ -121,14 +121,14 @@ body (nthnext form 3)] `(try ~@body - (cljs.test/do-report {:type :fail, :message ~msg, :expected '~form, :actual nil}) + (do-report {:type :fail, :message ~msg, :expected '~form, :actual nil}) (catch ~klass e# (let [m# (.-message e#)] (if (re-find ~re m#) - (cljs.test/do-report + (do-report {:type :pass, :message ~msg, :expected '~form, :actual e#}) - (cljs.test/do-report + (do-report {:type :fail, :message ~msg, :expected '~form, :actual e#})) e#))))) @@ -140,7 +140,7 @@ `(try ~(assert-expr &env msg form) (catch :default t# - (cljs.test/do-report + (do-report {:type :error, :message ~msg, :expected '~form, :actual t#})))) @@ -194,11 +194,11 @@ but must occur inside a test function (deftest)." ([string & body] `(do - (cljs.test/update-current-env! [:testing-contexts] conj ~string) + (update-current-env! [:testing-contexts] conj ~string) (try ~@body (finally - (cljs.test/update-current-env! [:testing-contexts] rest)))))) + (update-current-env! [:testing-contexts] rest)))))) ;; ============================================================================= ;; Defining Tests @@ -258,28 +258,28 @@ env (gensym "env") summary (gensym "summary")] `(let [~env ~(if is-ns - `(cljs.test/empty-env) + `(empty-env) env-or-ns) ~summary (cljs.core/volatile! {:test 0 :pass 0 :fail 0 :error 0 :type :summary})] (concat ~@(map (fn [ns] - `(concat (cljs.test/test-ns-block ~env ~ns) + `(concat (test-ns-block ~env ~ns) [(fn [] (cljs.core/vswap! ~summary (partial merge-with +) (:report-counters - (cljs.test/get-and-clear-env!))))])) + (get-and-clear-env!))))])) (if is-ns (concat [env-or-ns] namespaces) namespaces)) [(fn [] - (cljs.test/set-env! ~env) - (cljs.test/do-report (deref ~summary)) - (cljs.test/report (assoc (deref ~summary) :type :end-run-tests)) - (cljs.test/clear-env!))])))) + (set-env! ~env) + (do-report (deref ~summary)) + (report (assoc (deref ~summary) :type :end-run-tests)) + (clear-env!))])))) (defmacro run-tests "Runs all tests in the given namespaces; prints results. @@ -287,23 +287,23 @@ value due to the possiblity of asynchronous execution. To detect test completion add a :end-run-tests method case to the cljs.test/report multimethod." - ([] `(run-tests (cljs.test/empty-env) '~ana/*cljs-ns*)) + ([] `(run-tests (empty-env) '~ana/*cljs-ns*)) ([env-or-ns] (if (ns? env-or-ns) - `(run-tests (cljs.test/empty-env) ~env-or-ns) + `(run-tests (empty-env) ~env-or-ns) `(run-tests ~env-or-ns '~ana/*cljs-ns*))) ([env-or-ns & namespaces] - `(cljs.test/run-block (run-tests-block ~env-or-ns ~@namespaces)))) + `(run-block (run-tests-block ~env-or-ns ~@namespaces)))) (defmacro run-all-tests "Runs all tests in all namespaces; prints results. Optional argument is a regular expression; only namespaces with names matching the regular expression (with re-matches) will be tested." - ([] `(cljs.test/run-all-tests nil (cljs.test/empty-env))) - ([re] `(cljs.test/run-all-tests ~re (cljs.test/empty-env))) + ([] `(run-all-tests nil (empty-env))) + ([re] `(run-all-tests ~re (empty-env))) ([re env] - `(cljs.test/run-tests ~env + `(run-tests ~env ~@(map (fn [ns] `(quote ~ns)) (cond->> (ana-api/all-ns) @@ -311,18 +311,18 @@ (defmacro test-all-vars-block ([[quote ns]] - `(let [env# (cljs.test/get-current-env)] + `(let [env# (get-current-env)] (concat [(fn [] (when (nil? env#) - (cljs.test/set-env! (cljs.test/empty-env))) + (set-env! (empty-env))) ~(when (ana-api/ns-resolve ns 'cljs-test-once-fixtures) - `(cljs.test/update-current-env! [:once-fixtures] assoc '~ns + `(update-current-env! [:once-fixtures] assoc '~ns ~(symbol (name ns) "cljs-test-once-fixtures"))) ~(when (ana-api/ns-resolve ns 'cljs-test-each-fixtures) - `(cljs.test/update-current-env! [:each-fixtures] assoc '~ns + `(update-current-env! [:each-fixtures] assoc '~ns ~(symbol (name ns) "cljs-test-each-fixtures"))))] - (cljs.test/test-vars-block + (test-vars-block [~@(->> (ana-api/ns-interns ns) (filter (fn [[_ v]] (:test v))) (sort-by (fn [[_ v]] (:line v))) @@ -330,13 +330,13 @@ `(var ~(symbol (name ns) (name k))))))]) [(fn [] (when (nil? env#) - (cljs.test/clear-env!)))])))) + (clear-env!)))])))) (defmacro test-all-vars "Calls test-vars on every var with :test metadata interned in the namespace, with fixtures." [[quote ns :as form]] - `(cljs.test/run-block + `(run-block (concat (test-all-vars-block ~form) [(fn [] (report {:type :end-test-all-vars :ns ~form}))]))) @@ -348,15 +348,15 @@ (assert (and (= quote 'quote) (symbol? ns)) "Argument to test-ns must be a quoted symbol") (assert (ana-api/find-ns ns) (str "Namespace " ns " does not exist")) `[(fn [] - (cljs.test/set-env! ~env) - (cljs.test/do-report {:type :begin-test-ns, :ns ~form}) + (set-env! ~env) + (do-report {:type :begin-test-ns, :ns ~form}) ;; If the namespace has a test-ns-hook function, call that: ~(if-let [v (ana-api/ns-resolve ns 'test-ns-hook)] `(~(symbol (name ns) "test-ns-hook")) ;; Otherwise, just test every var in the namespace. - `(cljs.test/block (cljs.test/test-all-vars-block ~form)))) + `(block (test-all-vars-block ~form)))) (fn [] - (cljs.test/do-report {:type :end-test-ns, :ns ~form}))])) + (do-report {:type :end-test-ns, :ns ~form}))])) (defmacro test-ns "If the namespace defines a function named test-ns-hook, calls that. @@ -365,12 +365,12 @@ Internally binds *report-counters* to a ref initialized to *initial-report-counters*. " - ([ns] `(cljs.test/test-ns (cljs.test/empty-env) ~ns)) + ([ns] `(test-ns (empty-env) ~ns)) ([env [quote ns :as form]] - `(cljs.test/run-block - (concat (cljs.test/test-ns-block ~env ~form) + `(run-block + (concat (test-ns-block ~env ~form) [(fn [] - (cljs.test/clear-env!))])))) + (clear-env!))])))) ;; ============================================================================= ;; Fixes