 (ns cavm.query.expression
   (:require [clojure.edn :as edn])
   (:require [honeysql.types :as hsqltypes])
-  (:refer-clojure :exclude  [eval]))
+  (:refer-clojure :exclude [eval letfn]))
 
 (def eval)
 

      (eval body (cons (zipmap argnames args) scope)))))

(defn iffn [node scope]
  (let [[_ test then else] node]
    (cond
      (eval test scope) (eval then scope)
      :else (eval else scope))))

(def specials
  {'fn lambdafn
   'quote (fn [n s] (second n))
   'if iffn })

(def specialfns (set (vals specials)))


(defn eval [node scope]
  (cond
    (symbol? node) ((first (filter #(contains? % node) scope)) node)
    (seq? node) (fn-node node scope)
    (instance? Number node) (double node)
    (keyword? node) node
    (string? node) node
    ; due to weird (empty <clojure.lang.MapEntry>) behavior, we have
    ; to handle map? separate from coll?
    (map? node) (into {} (mapv #(eval (vec %) scope) node))
    (coll? node) (into (empty node) (mapv #(eval % scope) node))))

(defn expression [exp & globals]
  (eval (edn/read-string {:readers {'sql/call hsqltypes/read-sql-call}} exp) (cons specials globals)))
