         [midje.util.form-utils :only (pairs)])
   (:require [clojure.zip :as zip]))
 
+
+(defn first-true [preds & args]
+  (when (seq preds)
+    (if (apply (first preds) args)
+        (first preds)
+        (apply first-true (rest preds) args))))
+
+(defn translate [form & preds+translate-fns]
+  (loop [loc (zip/seq-zip form)]
+      (if (zip/end? loc)
+          (zip/root loc)
+          (if-let [true-fn (first-true (map first (partition 2 preds+translate-fns)) loc)]
+            (recur (zip/next ((get (apply hash-map preds+translate-fns) true-fn) loc)))
+            (recur (zip/next loc))))))
+
 ;; Translating a form into an equivalent form with all arrow sequences given
 ;; line numbers. 
 
 (defn add-line-numbers [form]
-  (loop [loc (zip/seq-zip form)]
-    (if (zip/end? loc)
-      (zip/root loc)
-      (recur (zip/next (cond (namespacey-match all-arrows loc)
-                             (add-line-number-to-end-of-arrow-sequence__then__no-movement
-                               (arrow-line-number loc) loc)
-                             
-                             :else loc))))))
-
-
+  (translate form
+    (fn [loc] (namespacey-match all-arrows loc))
+    (fn [loc] (add-line-number-to-end-of-arrow-sequence__then__no-movement (arrow-line-number loc) loc))))
 
  ;; Translating sweet forms into their semi-sweet equivalent

    (str "{" (str-join ", " entries) "}")))

(defn add-one-binding-note [expect-containing-form ordered-binding-map]
  (transform expect-containing-form
  	  loc-is-at-full-expect-form?
  	  (fn [loc] (skip-to-rightmost-leaf
             (add-key-value-within-arrow-branch__then__at_arrow :binding-note (binding-note ordered-binding-map) loc)))))

(defn add-binding-notes [expect-containing-forms ordered-binding-maps]
  (map (partial apply add-one-binding-note) 


(defn unfold-prerequisites [form]
  (with-fresh-generated-metadata-names
    (translate form
        loc-is-at-full-expect-form?
        unfold-expect-form__then__stay_put)))

