 ;; is still true.
 (defn overc [parent comp]
   "add given child as the comp child of the phrase: parent."
-
-  (log/trace (str "set? parent:" (set? parent)))
-  (log/trace (str "seq? parent:" (seq? parent)))
-  (log/trace (str "seq? comp:" (seq? comp)))
-
-  (log/trace (str "type of parent: " (type parent)))
-  (log/trace (str "type of comp  : " (type comp)))
-  (log/trace (str "nil? comp  : " (nil? comp)))
-
   (cond
-   (nil? comp) nil
-
-   (or
-    (seq? parent)
-    (set? parent)
-    (vector? parent))
+   (or (seq? parent)
+       (vector? parent))
    (let [parents (lazy-seq parent)]
      (mapcat (fn [parent]
                (overc parent comp))
              parents))
 
-   #?(:clj (future? comp))
-   #?(:clj (overc parent (deref comp)))
-
-   (or (set? comp)
-       (vector? comp))
-   (do (log/trace "comp is a set: converting to a seq.")
-       (overc parent (lazy-seq comp)))
+   (vector? comp)
+   (overc parent (lazy-seq comp))
 
    (seq? comp)
    (let [comp-children comp]
-     (log/trace (str "comp is a seq - actual type is " (type comp)))
-     (filter (fn [result]
-               (not (fail? result)))
-             (mapcat (fn [child]
-                       (overc parent child))
-                     comp-children)))
+     (mapcat (fn [child]
+               (overc parent child))
+             comp-children))
    true
    (let [result (unifyc parent
                         {:comp comp})


;; use map or pmap.
(def ^:const mapfn pmap)

(def ^:dynamic *extra-diagnostics* false)

(defn overh
  "add given head as the head child of the phrase: parent."
  [parent head]
  (when (and (map? parent)
             (map? head))
    (do
      (log/trace (str "overh: parent: " (get-in parent [:rule])))
      (log/trace (str "overh: head: " (get-in head [:rule] (str "head is a lexeme with pred: " (strip-refs (get-in head [:synsem :sem :pred]))))))
      (log/trace (str "overh: parent: " parent))
      (log/trace (str "overh: head: " head))))
  ;; TODO: get rid of all this type-checking and use
  ;; whatever people use for Clojure argument type-checking.
  (cond

   (nil? head)
   nil

   (or
    (seq? parent)
    (set? parent)
    (vector? parent))
   (let [parents (lazy-seq parent)]
     (filter (fn [result]
               (not (fail? result)))
             (mapcat (fn [each-parent]
                       (overh each-parent head))
                     parents)))

   (or (set? head)
       (vector? head))
   (do (log/trace "head is a set: converting to a seq.")
       (overh parent (lazy-seq head)))

   (seq? head)
   (let [head-children head]
     (log/trace (str "head is a seq - actual type is " (type head)))
     (filter (fn [result]
               (not (fail? result)))
             (mapcat (fn [child]
                       (overh parent child))
                     head-children)))
   true
   ;; TODO: 'true' here assumes that both parent and head are maps: make this assumption explicit,
   ;; and save 'true' for errors.
   (let [result (unify (copy parent)
                       {:head (copy head)})

         is-fail? (= :fail result)
         label (if (get-in parent [:rule]) (get-in parent [:rule]) (:comment parent))]
     (if (not is-fail?)
       (do
         (log/debug (str "overh: " (get-in parent [:rule]) " -> " (get-in head [:rule]
                                                                        (get-in head [:synsem :sem :pred]
                                                                                "(no pred for head)"))))
         (log/trace (str "overh successful result: " (strip-refs (dissoc result :dag_unify.core/serialized))))
         (list result))))))

;; Haskell-looking signature:
;; (parent:map) X (child:{set,seq,fs}) => list:map

;; 2) called with both a child1 and a child2, but child2's supplied value is nil:
;;    should be treated the same as empty list.
(defn over [parents child1 & [child2]]
  (cond (map? parents)
        (over (list parents) child1 child2)

        true
        (mapcat
         (fn [parent]
           (let [[head comp] (if (= (:first parent) :head)
                               [child1 child2]
                               [child2 child1])]
             (filter (fn [each]
                       (not (= :fail each)))
                     (overhc parent
                             (if (= (:first parent) :head)
                               child1 child2)
                             (if (= (:first parent) :head)
                               child2 child1)))))
         parents)))

(defn morph-with-recovery [morph-fn input]
  (if (nil? input)
