-(ns aurora.interprer)
+(ns aurora.interpreter)
 
 (declare run-node)
 

           ["four-a-c" ["four" "a" "c"] {:type :cljs :fn *}]
           ["result" ["b-squared" "four-a-c"] {:type :cljs :fn -}]]})

(run-node example [1 4 2] nil)

    (doseq [[id value] (map vector (:inputs node) inputs)]
      (aset vars id value))
    (doseq [[id node-inputs node] (:nodes node)]
      (aset vars id (run-node node (map #(aget vars %) node-inputs) actions)))
    (aget vars (-> node :nodes last first))))

(defn run-match [node inputs actions]
  (assert (= 1 (count inputs)))
  (run-match-branches (:branches node) (first inputs) actions))

(defrecord MatchFailure [])

(defn check [bool]
  (when-not bool (throw (MatchFailure.))))

(defn run-match-branches [branches input actions]
  (if-let [[[branch inputs node] & branches] (seq branches)]
    (try
      (let [vars #js {}]
        (run-match-branch branch input actions vars)
        (run-node node (map #(aget vars %) inputs) actions))
      (catch MatchFailure _
        (recur branches input actions)))
    (throw (MatchFailure.))))

(defn run-match-branch [branch input actions vars]
  (when-let [var (-> branch meta :var)]
    (aset vars var input))
  (cond
   (:type branch) (check (run-node branch [input] actions))
   (or (number? branch) (string? branch)) (check (= branch input))
   (or (nil? branch) (sequential? branch)) (if-let [[first-branch & rest-branch] (seq branch)]
                                             (do (check (and (sequential? input) (seq input)))
                                               (let [[first-input & rest-input] input]
                                                 (run-match-branch first-branch first-input actions vars)
                                                 (run-match-branch rest-branch rest-input actions vars)))
                                             (check (empty? input)))
   (map? branch) (do (check (map? input))
                   (doseq [[key val] branch]
                     (check (contains? input key))
                     (run-match-branch val (get input key) actions vars)))
   :otherwise (assert false)))

(defn run-node [node inputs actions]
  (:type node)
  (case (:type node)
    :value (run-value node inputs actions)
    :cljs (run-cljs node inputs actions)
    :match (run-match node inputs actions)
    :pipe (run-pipe node inputs actions)))

(def example-a
  {:type :pipe
   :inputs ["a" "b" "c"]
   :nodes [["b-squared" ["b" "b"] {:type :cljs :fn *}]
