    [clojure.string :refer (trim)]
    #?(:clj [clojure.tools.logging :as log])
    #?(:cljs [babel.logjs :as log])
-   [dag_unify.core :refer (copy dissoc-paths fail? get-in ref? strip-refs unifyc)]))
+   [dag_unify.core :refer (copy dissoc-paths fail? get-in ref? strip-refs unify unifyc)]))
 
 (def replace-patterns
   (concat

                                (log/debug (str "input spec: " (strip-refs unify-with)))
                                (log/debug (str "pattern spec:"  (strip-refs unify-against)))
                                (string/replace infinitive from to)))))
                        replace-patterns)))]
    (if (empty? result)
      (throw (Exception. (str "nothing found to match infinitive: " infinitive " ; "
                              " unify-with: " (strip-refs unify-with) ".")))

      (first result))))

;; TODO: separate part-of-speech -related functionality (e.g. the word is a verb) from
;; compositional functionality (e.g. the word has an :a and :b, so combine by concatenation, etc)
;; 
(defn get-string [word & [b]]
  (cond (and (nil? b)
             (seq? word))
        (let [result (get-string word)]

                          :infl :infinitive}}}})

(defn exception-generator [lexicon]
  (mapcat
   (fn [lexeme-kv]
          (let [lexemes (second lexeme-kv)
                result (mapcat (fn [path-and-merge-fn]
                                 (let [path (:path path-and-merge-fn)
                                       merge-fn (:merge-fn path-and-merge-fn)]
                                   ;; a lexeme-kv is a pair of a key
                                   ;; and value. The key is a
                                   ;; string (the word's surface form)
                                   ;; and the value is a list of lexemes for that string.
                                   (log/trace (str (first lexeme-kv) ": looking at path: " path))
                                   (mapcat (fn [lexeme]
                                             ;; this is where a unify/dissoc that supported
                                             ;; non-maps like :top and :fail, would be useful:
                                             ;; would not need the (if (not (fail? lexeme)..)) check
                                             ;; to avoid a difficult-to-understand
                                             ;; "java.lang.ClassCastException: clojure.lang.Keyword
                                             ;; cannot be cast to clojure.lang.IPersistentMap" error.
                                             (log/debug "lexeme: " (get-in lexeme [:français :français]))
                                             (log/debug " path: " path)
                                             (if-let [value (get-in lexeme path)]
                                               (log/debug " value@" path ": " value))
                                             (if (not (= ::none (get-in lexeme path ::none)))
                                               (let [exceptional-lexeme
                                                     (apply merge-fn (list lexeme))]
                                                 (log/debug " exceptional-lexeme: " exceptional-lexeme)
                                                 (cond (or (seq? exceptional-lexeme)
                                                           (vector? exceptional-lexeme))
                                                       (map (fn [exceptional-lexeme]
                                                              (log/debug " RESULT(in-list): " exceptional-lexeme)
                                                              (log/debug "   conjugated:"
                                                                         (get-in exceptional-lexeme
                                                                                 [:français :français]))
                                                              (let [exceptional-lexeme
                                                                    (unify
                                                                     exceptional-lexeme
                                                                     (dissoc-paths lexeme [path
                                                                                           [:français :français]])
                                                                     {:français {:exception true}})]
                                                                (log/debug " RESULT(in-list)1: "
                                                                           (dissoc
                                                                            exceptional-lexeme
                                                                            :dag_unify.core/serialized))
                                                                {(get-in exceptional-lexeme [:français :français])
                                                                 exceptional-lexeme}))
                                                            exceptional-lexeme)
                                                       
                                                       true
                                                       (let [exceptional-lexeme
                                                             (unify
                                                              exceptional-lexeme
                                                              (dissoc-paths lexeme [path
                                                                                    [:français :français]])
                                                              {:français {:exception true}})]
                                                         (log/debug " RESULT1: "
                                                                    (unify
                                                                     exceptional-lexeme
                                                                     (dissoc-paths lexeme [path
                                                                                           [:français :français]])))
                                                         (log/debug " RESULT2: "
                                                                    (dissoc
                                                                     exceptional-lexeme
                                                                     :dag_unify.core/serialized))
                                                         (list {(get-in exceptional-lexeme [:français :français])
                                                                exceptional-lexeme}))))))
                                           lexemes)))
                               [;; 1. past-tense exceptions
                                {:path [:français :past-participle]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :past-p
                                               :français (get-in val [:français :past-participle] :nothing)}})}
                                ;; 2. present-tense exceptions
                                {:path [:français :present :1sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :1sing] :nothing)
                                               :agr {:number :sing
                                                     :person :1st}}})}
                                {:path [:français :present :2sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :2sing] :nothing)
                                               :agr {:number :sing
                                                     :person :2nd}}})}
                                {:path [:français :present :3sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :3sing] :nothing)
                                               :agr {:number :sing
                                                     :person :3rd}}})}
                                {:path [:français :present :1plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :1plur] :nothing)
                                               :agr {:number :plur
                                                     :person :1st}}})}
                                {:path [:français :present :2plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :2plur] :nothing)
                                               :agr {:number :plur
                                                     :person :2nd}}})}
                                {:path [:français :present :3plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :present
                                               :français (get-in val [:français :present :3plur] :nothing)
                                               :agr {:number :plur
                                                     :person :3rd}}})}
                                ;; 3. imperfect-tense exceptions
                                {:path [:français :imperfect :1sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :1sing] :nothing)
                                               :agr {:number :sing
                                                     :person :1st}}})}
                                {:path [:français :imperfect :2sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :2sing] :nothing)
                                               :agr {:number :sing
                                                     :person :2nd}}})}
                                {:path [:français :imperfect :3sing]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :3sing] :nothing)
                                               :agr {:number :sing
                                                     :person :3rd}}})}
                                {:path [:français :imperfect :1plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :1plur] :nothing)
                                               :agr {:number :plur
                                                     :person :1st}}})}
                                {:path [:français :imperfect :2plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :2plur] :nothing)
                                               :agr {:number :plur
                                                     :person :2nd}}})}
                                {:path [:français :imperfect :3plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:infl :imperfect
                                               :français (get-in val [:français :imperfect :3plur] :nothing)
                                               :agr {:number :plur
                                                     :person :3rd}}})}
                                ;; 3. present-tense boot-stem exception: :boot-stem1.
                                {:path [:français :boot-stem1]
                                 :merge-fn
                                 (fn [val]
                                   [{:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem1])
                                                               "s")
                                                :agr {:number :sing
                                                      :person :1st}}}
                                    {:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem1])
                                                               "s")
                                                :agr {:number :sing
                                                      :person :2nd}}}
                                    {:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem1])
                                                               "t")
                                                :agr {:number :sing
                                                      :person :3rd}}}
                                    {:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem1])
                                                               "vent")
                                                :agr {:number :plur
                                                      :person :3rd}}}])}

                                {:path [:français :boot-stem2]
                                 :merge-fn
                                 (fn [val]
                                   [{:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem2])
                                                               "ons")
                                                :agr {:number :plur
                                                      :person :1st}}}
                                    {:français {:infl :present
                                                :français (str (get-in val [:français :boot-stem2])
                                                               "ez")
                                                :agr {:number :plur
                                                      :person :2nd}}}])}

                                
                                ;; 4. adjectives
                                {:path [:français :masc :plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:agr {:gender :masc
                                                     :number :plur}}})}
                                {:path [:français :fem :plur]
                                 :merge-fn
                                 (fn [val]
                                   {:français {:agr {:gender :fem
                                                     :number :plur}}})}
                                ])]
            result))
   lexicon))

(defn phonize [a-map a-string]
  (let [common {:phrasal false}]
