                                     (concat [~@(map #(list `vector (keyword %) %) base-fields)]
                                             ~'__extmap))))
                   ])
-          [fpps pmasks] (prepare-protocol-masks env tagname impls)
+          [fpps pmasks] (prepare-protocol-masks env impls)
           protocols (collect-protocols impls env)
           tagname (vary-meta tagname assoc
                     :protocols protocols

(defn prototype-prefix [tsym sym]
  `(.. ~tsym -prototype ~(to-property sym)))

(defmacro extend-type [tsym & impls]
  (let [env       &env
        resolve   (partial resolve-var env)
        impl-map  (->impl-map impls)
        skip-flag (set (-> tsym meta :skip-protocol-flag))]
    (if-let [type (base-type tsym)]
      `(do ~@(mapcat #(base-assign-impls env resolve tsym type %) impl-map))
      (let [t (resolve tsym)
            assign-impls (fn [[p sigs]]
                           (warn-and-update-protocol p t &env)
                           (let [psym (resolve p)
                                 pprefix (protocol-prefix psym)]
                             (if (= p 'Object)
                               (let [adapt-params (fn [[sig & body]]
                                                    (let [[tname & args] sig]
                                                      (list (vec args) (list* 'this-as (vary-meta tname assoc :tag t) body))))]
                                 (map (fn [[f & meths :as form]]
                                        `(set! ~(prototype-prefix tsym f)
                                               ~(with-meta `(fn ~@(map adapt-params meths)) (meta form))))
                                      sigs))
                               (concat (when-not (skip-flag psym)
                                         [`(set! ~(prototype-prefix tsym pprefix) true)])
                                       (mapcat (fn [[f & meths :as form]]
                                                 (if (= psym 'cljs.core/IFn)
                                                   (let [adapt-params (fn [[[targ & args :as sig] & body]]
                                                                        (let [this-sym (with-meta 'self__ {:tag t})]
                                                                          `(~(vec (cons this-sym args))
                                                                            (this-as ~this-sym
                                                                                     (let [~targ ~this-sym]
                                                                                       ~@body)))))
                                                         meths (map adapt-params meths)
                                                         this-sym (with-meta 'self__ {:tag t})
                                                         argsym (gensym "args")]
                                                     [`(set! ~(prototype-prefix tsym 'call) ~(with-meta `(fn ~@meths) (meta form)))
                                                      `(set! ~(prototype-prefix tsym 'apply)
                                                             ~(with-meta
                                                                `(fn ~[this-sym argsym]
                                                                   (this-as ~this-sym
                                                                     (.apply (.-call ~this-sym) ~this-sym
                                                                       (.concat (array ~this-sym) (aclone ~argsym)))))
                                                                (meta form)))])
                                                   (let [pf (core/str pprefix f)
                                                         adapt-params (fn [[[targ & args :as sig] & body]]
                                                                        `(~(vec (cons (vary-meta targ assoc :tag t) args))
                                                                           (this-as ~targ
                                                                             ~@body)))]
                                                     (if (vector? (first meths))
                                                       [`(set! ~(prototype-prefix tsym (core/str pf "$arity$" (count (first meths)))) ~(with-meta `(fn ~@(adapt-params meths)) (meta form)))]
                                                       (map (fn [[sig & body :as meth]]
                                                              `(set! ~(prototype-prefix tsym (core/str pf "$arity$" (count sig)))
                                                                     ~(with-meta `(fn ~(adapt-params meth)) (meta form))))
                                                            meths)))))
                                               sigs)))))]
        `(do ~@(mapcat assign-impls impl-map))))))

(defn- prepare-protocol-masks [env t impls]
  (let [resolve #(let [ret (:name (cljs.analyzer/resolve-var (dissoc env :locals) %))]
                   (assert ret (core/str "Can't resolve: " %))
                   ret)
        impl-map (loop [ret {} s impls]
                   (if (seq s)
                     (recur (assoc ret (first s) (take-while seq? (next s)))
                            (drop-while seq? (next s)))
                     ret))]
    (if-let [fpp-pbs (seq (keep fast-path-protocols
                                (map resolve
                                     (keys impl-map))))]
      (let [fpps (into #{} (filter (partial contains? fast-path-protocols)
                                   (map resolve
                                        (keys impl-map))))
            fpp-partitions (group-by first fpp-pbs)
            fpp-partitions (into {} (map (juxt key (comp (partial map peek) val))
                                         fpp-partitions))
            fpp-partitions (into {} (map (juxt key (comp (partial reduce core/bit-or) val))
                                         fpp-partitions))]
        [fpps
         (reduce (fn [ps p]
                   (update-in ps [p] (fnil identity 0)))
                 fpp-partitions
                 (range fast-path-protocol-partitions-count))]))))

(defn dt->et
  ([t specs fields] (dt->et t specs fields false))
  ([t specs fields inline]
     (loop [ret [] s specs]
       (if (seq s)
         (recur (-> ret
                    (conj (first s))
                    (into
                      (reduce (fn [v [f sigs]]
                                (conj v (vary-meta (cons f (map #(cons (second %) (nnext %)) sigs))
                                                   assoc :cljs.analyzer/type t
                                                         :cljs.analyzer/fields fields
                                                         :protocol-impl true
                                                         :protocol-inline inline)))
                              []
                              (group-by first (take-while seq? (next s))))))
                (drop-while seq? (next s)))
         ret))))

(defn collect-protocols [impls env]
  (->> impls


(defmacro deftype [t fields & impls]
  (let [r (:name (cljs.analyzer/resolve-var (dissoc &env :locals) t))
        [fpps pmasks] (prepare-protocol-masks &env impls)
        protocols (collect-protocols impls &env)
        t (vary-meta t assoc
            :protocols protocols
