Last active
August 29, 2015 14:01
-
-
Save aamedina/c26a0b8a243c85810044 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| (ns cljc.core | |
| (:refer-clojure :exclude [fn reify deftype])) | |
| (defmacro reify | |
| [& impls] | |
| `(clojure.core/reify ~@impls)) | |
| (defmacro deftype | |
| [t fields & impls] | |
| `(clojure.core/deftype ~t ~fields ~@impls)) | |
| (def | |
| ^{:macro true | |
| :arglists '([name doc-string? [params*] & body])} | |
| defmacro1 | |
| (reify clojure.lang.IFn | |
| (invoke [_ &form &env name args] | |
| (let [[doc-string? args body] | |
| (cond | |
| (string? (first args)) [(first args) (second args) (nnext args)] | |
| (vector? (first args)) [nil (first args) (rest args)] | |
| :else (throw (ex-info "Args must be in vector" {})))] | |
| (list 'do | |
| (list 'def (with-meta name {:macro true :doc doc-string?}) | |
| `(reify clojure.lang.IFn | |
| (invoke [_ &form &env ~@args] | |
| ~@body))) | |
| (list 'var name)))))) | |
| (defmacro fn | |
| [& sigs] | |
| (let [env &env | |
| mform (macroexpand (list* 'clojure.core/fn sigs)) | |
| [sym sigs] (if (symbol? (second mform)) | |
| [(second mform) (nnext mform)] | |
| [nil (next mform)]) | |
| variadic? (some #(contains? (set %) '&) (map first sigs)) | |
| [sigs variadic] (if-let [sigs (partition-by #(contains? (set (first %)) | |
| '&) sigs)] | |
| (if (== (count sigs) 2) | |
| sigs | |
| [nil (first sigs)])) | |
| variadic | |
| (if (> (count variadic) 1) | |
| (throw (ex-info "Can't have more than 1 variadic overload" {})) | |
| (first variadic)) | |
| variadic-arity (when variadic (dec (count (first variadic)))) | |
| max-fixed-arity (when sigs (apply max (map (comp count first) sigs))) | |
| sigs | |
| (mapv (reify clojure.lang.IFn | |
| (invoke [_ sig] | |
| (let [[args & body] sig | |
| params (repeatedly (count args) gensym)] | |
| (list 'invoke (into [(gensym)] params) | |
| (list* 'let [(vec args) (vec params)] body))))) sigs) | |
| sigs (if (nil? variadic) | |
| sigs | |
| (let [[args & body] variadic | |
| params (vec (repeatedly (inc variadic-arity) gensym))] | |
| (conj sigs (list 'invoke params | |
| (list* 'let (if (> (count args) 2) | |
| [(vec (drop-last 2 args)) | |
| (vec (butlast (next params))) | |
| (vec (take-last 2 args)) | |
| (last params)] | |
| [(vec args) | |
| (last params)]) | |
| body)))))] | |
| `(with-meta (reify clojure.lang.Fn | |
| clojure.lang.IFn | |
| ~@sigs) {:tag ~(:tag (meta sym))}))) | |
| (defmacro defn | |
| [name args & body] | |
| `(def ~name (fn ~name ~args ~@body))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment