 (ns aurora.interpreter)
+
+;; interpreter
 
 (defn run-pipe [program node inputs actions]
   (let [vars #js {}]

(defn run-ref [program node inputs actions]
  (case (:kind node)
    :cljs (apply (:fn node) inputs)
    :aurora (run-node program (get program (:id node)) inputs actions)))

(defrecord MatchFailure [])


                     (run-match-pattern program val (get input key) actions vars)))
   :otherwise (assert false)))

;; ast

(defn pipe [inputs & nodes]
  {:type :pipe
   :inputs inputs
   :nodes (for [[id inputs node] (partition 3 nodes)]
            {:id id :inputs inputs :node node})})

(defn value [x]
  {:type :value :value x})

(defn cljs-ref [fn]
  {:type :ref :kind :cljs :fn fn})

(defn pipe-ref [id]
  {:type :ref :kind :pipe :id id})

(defn match [& branches]
  {:type :match
   :branches (for [[pattern inputs node] (partition 3 branches)]
               {:pattern pattern :inputs inputs :node node})})

(defn bind [var pattern]
  {:type :match/bind
   :var var
   :pattern pattern})

;; examples

(def example-a
  {"root" (pipe ["a" "b" "c"]
                "b-squared" ["b" "b"] (cljs-ref *)
                "four" [] (value 4)
                "four-a-c" ["four" "a" "c"] (cljs-ref *)
                "result" ["b-squared" "four-a-c"] (cljs-ref -))})

(def example-b
  {"root" (pipe ["x"]
                "result" ["x"] (match {"a" (bind "a" (cljs-ref number?)) "b" (bind "b" (cljs-ref number?))} ["a" "b"] (cljs-ref -)
                                      [(bind "x" (value true)) "foo"] ["x"] (cljs-ref identity)))})

(def example-c
  {"root" (pipe-ref "even?")
   "even?" (pipe ["x"]
                 "result" ["x"] (match 0 [] (value true)
                                       (bind "x" (value true)) ["x"] (pipe-ref "even?not-0")))
   "even?not-0" (pipe ["x"]
                      "one" [] (value 1)
                      "x-1" ["x" "one"] (cljs-ref -)
                      "odd?" ["x-1"] (pipe-ref "odd?")
                      "result" ["odd?"] (cljs-ref not))
   "odd?" (pipe ["x"]
                "result" ["x"] (match 0 [] (value true)
                                      (bind "x" (value true)) ["x"] (pipe-ref "odd?not-0")))
   "odd?not-0" (pipe ["x"]
                     "one" [] (value 1)
                     "x-1" ["x" "one"] (cljs-ref -)
                     "even?" ["x-1"] (pipe-ref "even?")
                     "result" ["even?"] (cljs-ref not))})

(defn run-example [example inputs]
  (try
