(ns emptyhead.thought.define
  "Utilities for defining new thoughts."
  (:require [emptyhead.thought.crud :as thought]
            [emptyhead.thought.eval :as eval]
            [emptyhead.idea.crud :as idea]))

(defn register-implementation!
  [operator impl]
  (idea/have-idea! :prefix (str "impl_thought_" (name operator))
                   :properties [[:thought-impl operator]]
                   :data {:implementation impl}))

(defn register-constructor!
  [operator & {:keys [constr-fn defaults]
               :or {constr-fn identity
                    defaults {}}}]
  (let [constr-op (keyword (str (name operator) ".construct"))]
    (register-implementation!
     constr-op
     (fn [thought & [parent]]
       [parent
       (thought/register-thought!
        operator
        (merge defaults {:operator operator}
               (constr-fn (merge parent thought))))]))))

(defn define!
  [operator impl & {:keys [constr-fn defaults]
                    :as constr-args}]
  (register-implementation! operator impl)
  (register-constructor! operator constr-args))
