Skip to content

Instantly share code, notes, and snippets.

@selfsame
Last active August 29, 2015 14:18
Show Gist options
  • Select an option

  • Save selfsame/dee7fce665ea9836ac3e to your computer and use it in GitHub Desktop.

Select an option

Save selfsame/dee7fce665ea9836ac3e to your computer and use it in GitHub Desktop.
(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