                                 (get lexicon lex)))))))
            replace-patterns)))
 
-(defn conjugate [infinitive unify-with]
+(defn conjugate [infinitive unify-with & [lexicon]]
   "Conjugate an infinitive into a surface form by taking the first 
    element of replace-patterns where the element's :u unifies successfully with
-   unify-with."
-  (let [result
-        (take 1
-              (remove #(nil? %)
-                      (map
-                       (fn [replace-pattern]
-                         (let [from (nth (:g replace-pattern) 0)
-                               to (nth (:g replace-pattern) 1)
-                               unify-against (if (:u replace-pattern)
-                                               (:u replace-pattern)
-                                               :top)]
+   unify-with. If lexicon is supplied, look up infinitive in lexicon and use exceptional form of
+   first return value, if any."
+  (let [exception (let [exception (first (get lexicon infinitive))
+                        boot-stem1 (get-in exception [:français :boot-stem])
+                        boot-stem2 (get-in exception [:français :boot-stem2])
+                        present-1-sing (get-in exception [:français :present :1sing])
+                        present-2-sing (get-in exception [:français :present :2sing])
+                        present-3-sing (get-in exception [:français :present :3sing])]
+                    (if exception
+                      [(cond
+                         (and present-1-sing
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :1st
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         present-1-sing
+
+                         (and present-2-sing
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :2nd
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         present-2-sing
+
+                         (and present-3-sing
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :3rd
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         present-3-sing
+
+                         (and boot-stem1
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :1st
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         (str boot-stem1 "s")
+
+                         (and boot-stem1
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :2nd
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         (str boot-stem1 "s")
+
+                         (and boot-stem1
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :3rd
+                                                                        :number :sing}}}}}
+                                           unify-with))))
+                         (str boot-stem1 "t")
+
+                         (and boot-stem2
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :1st
+                                                                        :number :plur}}}}}
+                                           unify-with))))
+                         (str boot-stem2 "ons")
+
+                         (and boot-stem2
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :2nd
+                                                                        :number :plur}}}}}
+                                           unify-with))))
+                         (str boot-stem2 "ez")
+
+                         (and boot-stem1
+                              (not (fail?
+                                    (unify {:synsem {:infl :present
+                                                     :subcat {:1 {:agr {:person :3rd
+                                                                        :number :plur}}}}}
+                                           unify-with))))
+                         (str boot-stem1 "ent")
+
+                         true nil)]))
+        result
+        (or exception
+            (take 1
+                  (remove #(nil? %)
+                          (map
+                           (fn [replace-pattern]
+                             (let [from (nth (:g replace-pattern) 0)
+                                   to (nth (:g replace-pattern) 1)
+                                   unify-against (if (:u replace-pattern)
+                                                   (:u replace-pattern)
+                                                   :top)]
                             (if (and from to
                                      (re-matches from infinitive)
                                      (not (fail? (unifyc unify-against

                                      ;; TODO: add checks for other -stem features, like :imperfect-stem.
                                      true
                                      (get-in word [:français]))]
                 (log/info (str "conjugate: infinitive=" infinitive "; word=" word))
                 (conjugate infinitive word))))
           
           (and

                          :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}]
