 (defvar merlin-buffer nil
   "Buffer for merlin input.")
 (make-variable-buffer-local 'merlin-buffer)
-
-;; Those variables will be bound dynamically in the scope of asynchronous
-;; closures (merlin-send-command-async & merlin-wait-for-answer)
-; (defvar merlin-result nil
-;   "Temporary variables to store command results.")
-; (make-variable-buffer-local 'merlin-result)
-
-; (defvar merlin-ready nil
-;   "If non-nil, the reception is done.")
-; (make-variable-buffer-local 'merlin-ready)
 
 (defvar merlin-dirty-point 0
   "Position after which buffer content may differ.")

      (ignore-errors (kill-process merlin-process)))
    (kill-buffer buffer)))

(defun merlin-wait-for-answer ()
  "Waits for merlin to answer."
  (let ((w32-pipe-read-delay 0)) ;; fix 50ms latency of emacs on win32
    (while (not merlin-ready)
      (accept-process-output (merlin-process) 0.1 nil t)))
  merlin-result)

(defun merlin--reset ()
  "Rewind the knowledge of merlin of the current buffer to zero."

    (merlin--reset)
    (merlin--check-project-file)))

(defun merlin-send-command-async-handler (closure answer)
  "Callback sent by merlin-send-command-async to tq-enqueue."
  (let ((promise       (elt closure 0))
        (cb-if-success (elt closure 1))
        (cb-if-exn     (elt closure 2))
        (command       (elt closure 3))
        (buffer        (elt closure 4)))
    (setcar promise t)
    (with-current-buffer buffer
      (when merlin-debug (merlin-debug (format "<%s" answer)))
      (setq answer (car (read-from-string answer)))
      (cond ((not answer)
             (message "Invalid answer received from merlin."))
            ((string-equal (elt answer 0) "return")
             (setcdr promise (funcall cb-if-success (elt answer 1)))
             ((string-equal (elt answer 0) "exception")
              (message "Merlin failed with exception: %s" (elt answer 1)))
             ((if (functionp cb-if-exn)
                  (setcdr promise (funcall cb-if-exn (elt answer 1)))
                (message "Command %s failed with error %s" command (elt answer 1)))))))))

(defun merlin-send-command-async (command callback-if-success &optional callback-if-exn)
  "Send COMMAND (with arguments ARGS) to merlin asynchronously.
Give the result to callback-if-success.  If merlin reported an
error and if CALLBACK-IF-EXN is non-nil, call the function with
the error message otherwise print a generic error message."
  (assert (merlin--acquired-buffer))
  (let* ((string (concat (prin1-to-string (if (listp command) command (list command))) "\n"))
         (promise (cons nil nil))
         (closure (list promise
                        callback-if-success
                        callback-if-exn
                        command
                        (current-buffer))))
    (if (not (equal (process-status (merlin-process)) 'run))
        (progn (error "Merlin process not running (try restarting with %s)"
                      (substitute-command-keys "\\[merlin-restart-process]"))
               nil)
      (with-current-buffer (merlin-process-buffer)
        (when merlin-debug
          (merlin-debug (format ">%s" string)))
        (tq-enqueue merlin-process-queue string "\n"
                    closure #'merlin-send-command-async-handler)
        promise))))

(defun merlin-send-command (command &optional callback-if-exn)
  "Send COMMAND (with arguments ARGS) to merlin and returns the result."
  (merlin--wait-for-answer (merlin-send-command-async
                            command (lambda (data) data) callback-if-exn)))

;; SPECIAL CASE OF COMMANDS

