Last active
August 29, 2015 14:18
-
-
Save selfsame/dee7fce665ea9836ac3e 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 story.core | |
| (import [UnityEngine Vector3 Vector2 Color])) | |
| (def __R (atom {})) | |
| (defn- arity-match [given pattern] | |
| (every? true? | |
| (map #(or (nil? %1) (= %1 %2)) | |
| pattern given))) | |
| (defn- arity-matcher [pattern] | |
| (let [code (remove nil? (map #(if % (list '= 'x %) nil) pattern))] ;('type 'x) | |
| (eval (list 'fn '[x] (cond (empty? code) true | |
| (= (count code) 1) (first code) | |
| :else (cons 'and code)))))) | |
| (defn -invoke [sym arity-count args] | |
| (if-let [arity-entries (get (get @__R sym) arity-count)] | |
| (let [arg-types (map type args) | |
| arity-t (filter #(% args)) | |
| pull-t (mapcat #(get arity-entries %)) | |
| pre-t (filter (fn [[k v]] (try (if (apply k args) true false) (catch Exception e false)))) | |
| res (last (first (sequence (comp arity-t pull-t pre-t) (keys arity-entries))))] | |
| (when res (apply res args))))) | |
| (defn register [sym arg-len arg-types conditions f] | |
| (swap! __R update-in [sym arg-len] #(merge-with merge % {(arity-matcher arg-types) {conditions f}})) | |
| #(-invoke sym arg-len %&)) | |
| (defn- make-conditional [args m] | |
| (let [arg-idxs (into {} (into {} (map-indexed #(vector %2 %1) args)))] | |
| (list 'fn args | |
| (cons 'and | |
| (map (fn [[k v]] | |
| (cond (= :when k) v | |
| (get arg-idxs k) | |
| (list v k))) m))))) | |
| (defmacro rule [name args & more] | |
| (let [arg-len (count args) | |
| arg-types (mapv (comp :tag meta) args) | |
| -when (if (map? (first more)) (first more)) | |
| code (if -when (rest more) more) | |
| conditions (make-conditional args (or -when {}))] | |
| `(do | |
| (def ~name | |
| (register (var ~name) ~arg-len ~arg-types ~conditions (fn ~args ~@code)) | |
| )))) | |
| (defmacro before []) | |
| (defmacro after []) | |
| (defn non [f] (fn [x] (not (f x)))) | |
| (rule divide [a b] | |
| {a number? | |
| b (comp (non zero?) number?)} | |
| (/ a b)) | |
| (rule divide [^Vector3 a b] | |
| {b (comp (non zero?) number?)} | |
| (Vector3/op_Division a b)) | |
| (rule divide [^System.Double a b] | |
| {b (comp (non zero?) number?)} | |
| (+ a b)) | |
| (rule divide [^Vector3 a b] | |
| {b neg?} | |
| (Vector3/op_Division a b)) | |
| (divide 1 5) | |
| (divide (Vector3. 4 5 6) 1) | |
| (time (dotimes [i 10000] (divide (Vector3. 4 5 6) -2))) | |
| (time (dotimes [i 10000] (Vector3/op_Division (Vector3. 4 5 6) 2))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment