 
 (def ^:dynamic *locals*)
 (defn eval-with-locals
-  "Evals a form with given locals. The locals should be a map of symbols to
-  values."
+  "Evals a form with given locals.
+  The locals should be a map of symbols to values."
   [locals form]
   (binding [*locals* locals]
     (eval

(defmacro try-repl [body-form]
  `(try
     ~body-form
     (catch Exception ex#
       (debug-repl))))

(defn make-error-handler
  "This takes a function that takes two args

  (throw quit-dr-exception))

(defn caught [exc]
  (if (or (= exc quit-dr-exception)
          (= (.getCause ^Throwable exc) quit-dr-exception))
    (throw quit-dr-exception)
    (clojure.main/repl-caught exc)))

(defmacro debug-repl
  "Starts a REPL with the local bindings available."
  ([]
   `(debug-repl nil ~(meta &form)))
  ([retform]
   `(debug-repl retform ~(meta &form)))
  ([retform form-meta]
   `(let [debug-meta# ~(assoc form-meta
                              :ns *ns*
                              :file *file*)
          eval-fn# (fn [e-form#]
                     (eval-with-locals (merge {(symbol "debug-meta") debug-meta#
                                               (symbol "in-debug-ns") (fn [] (in-ns (ns-name (:ns debug-meta#))))}
                                              (local-bindings)
                                              {(symbol "quit-dr") ~quit-dr}) e-form#))]
      (try
        (binding [level (unchecked-inc level)]
          (clojure.main/repl
            :init (fn []
                    (use 'clojure.core)
                    (use 'clojure.repl))
            :prompt #(print (str "dr-" level "-" (inc-counter) " [" *ns* "]=> "))
            :eval eval-fn#
            :read dr-read
            :caught caught))
        (catch Exception e#
          (if (= e# quit-dr-exception)
            (if-let [new-form# (.nextElement ^java.util.Enumeration quit-dr-exception)]
              (eval-fn# new-form#)
              (eval-fn# ~retform))
            (throw e#)))))))

(defmacro assert-repl [assertion-form]
