 
                             (take max-generated-complements (lazy-cat phrasal-complements filtered-lexical-complements)))))))))
 
+(defn candidate-parents [rules spec]
+  "find subset of _rules_ for which each member unifies successfully with _spec_"
+  (log/trace (str "candidate-parents: spec: " (strip-refs spec)))
+  (filter #(not (= :fail %))
+          (pmap (fn [rule]
+                  (log/trace (str "candidate-parents: rule: " (:rule rule)))
+                  (if (and (not (fail? (unifyc (get-in rule [:synsem :cat] :top)
+                                               (get-in spec [:synsem :cat] :top))))
+                           (not (fail? (unifyc (get-in rule [:synsem :infl] :top)
+                                               (get-in spec [:synsem :infl] :top))))
+                           (not (fail? (unifyc (get-in rule [:synsem :sem :tense] :top)
+                                               (get-in spec [:synsem :sem :tense] :top))))
+                           (not (fail? (unifyc (get-in rule [:synsem :modified] :top)
+                                               (get-in spec [:synsem :modified] :top)))))
+                    (let [result
+                           (unifyc spec rule)]
+                      (if (fail? result)
+                        :fail
+                        result))
+                    :fail))
+                rules)))
+
+(defn lazy-shuffle [seq]
+  (lazy-seq (shuffle seq)))
+
+(defn exception [error-string]
+  #?(:clj
+     (throw (Exception. (str ": " error-string))))
+  #?(:cljs
+     (throw (js/Error. error-string))))
+
+(defn current-time []
+  #?(:clj (System/currentTimeMillis))
+  #?(:cljs (.getTime (js/Date.))))
+
+;; Thanks to http://clojurian.blogspot.com.br/2012/11/beware-of-mapcat.html
+(defn lazy-mapcat  [f coll]
+  (lazy-seq
+   (if (not-empty coll)
+     (concat
+      (f (first coll))
+      (lazy-mapcat f (rest coll))))))
+
+(defn path-to-map [path val]
+  (let [feat (first path)]
+    (if feat
+      {feat (path-to-map (rest path) val)}
+      val)))
+
+(defn lexemes-before-phrases [depth max-total-depth]
+  "returns true or false: true means generate by adding lexemes first; otherwise, by adding phrases first. Takes depth as an argument, which makes returning true (i.e. lexemes first) increasingly likely as depth increases."
+  (if (not randomize-lexemes-before-phrases)
+    false
+    (if (> max-total-depth 0)
+      (let [prob (- 1.0 (/ (- max-total-depth depth)
+                           max-total-depth))]
+        (log/trace (str "P(c," depth ") = " prob " (c: probablity of choosing lexemes rather than phrases given a depth)."))
+        (> (* 10 prob) (rand-int 10)))
+      false)))
+
 (defn spec-info [spec]
   "give a human-readable summary of _spec_."
   (strip-refs

                                   truncate-children max-total-depth))
       (do (log-bolt-groups bolt-groups language-model)
           (reduce concat bolt-groups))))))

(defn log-bolt-groups [bolt-groups language-model]
  (log/trace
   (str "bolt-groups:\n"
        (string/join "\n"
                     (map (fn [bolt-group]
                            (str "bolt-group:\n"
                                 (string/join "\n"
                                              (map (fn [bolt]
                                                     (str " " (show-bolt bolt language-model)))
                                                   bolt-group))))
                          bolt-groups)))))

;; TODO: make this non-recursive by using mapcat.
(defn add-all-comps-with-paths [bolts language-model total-depth comp-paths truncate-children max-total-depth]

        ;; total-depth, on the other hand, is the depth all the way to the top of the entire
        ;; expression, which might involve several parent lightning bolts.
        parents (shuffle (candidate-parents grammar spec))]
    (log/debug (str "lightning-bolt: candidate-parents: [" (string/join "," (map :rule parents)) "] for spec:" (strip-refs spec)))
    (let [lexical ;; 1. generate list of all phrases where the head child of each parent is a lexeme.
          (when (= false (get-in spec [:head :phrasal] false))
            (mapfn (fn [parent]
