Generate a defmacro form that transforms code like this:
(with-iterators ((it1 seq1 :start start1 :end end1 :from-end from-end) (it2 seq2 :start start2 :end end2 :from-end from-end)) (loop do (with-iter-place (e1 it1 more1?) (with-iter-place (e2 it2 more2?) (when (not (and more1? more2?)) (return-from mismatch (when (or more1? more2?) (compute-pos pos)))) (unless (funcall test (funcall key e1) (funcall key e2)) (return-from mismatch (compute-pos pos))) (cl:incf pos)))))

Pattern to recognize: Macro call that should be transformed by with-iterators

Macro definition:
(defmacro with-iterators (seqs &body forms &environment env)
  "Create static iterators for one or more sequence.

   This macro attempts to determine the type of each sequence, and calls
   MAKE-DOSEQ to generate optimal static iterator code for the given
   sequence types, rather than creating dynamic iterator objects.

   SEQS:

     A list where each element is of the form (ITER SEQUENCE . ARGS)
     where ITER is a symbol identifying the iterator for the sequence,
     SEQUENCE is the form which evaluates to a sequence, and ARGS are
     the remaining iteration arguments, interpreted as they are to the
     ITERATOR function.

     Each iterator identifier (ITER) can be passed to
     WITH-ITER-VALUE, within the body forms of WITH-ITERATORS, to
     retrieve the values of the elements of the sequence.

     The iterator identifiers are in a namespace of their own that is
     they do not name lexical variables/symbol-macros nor functions/macros.


   FORMS:

     A list of forms evaluated in an implicit TAGBODY, thus symbols
     are interpreted as tag names.

     The WITH-ITER-VALUE macro can be used, within FORMS, to retrieve
     the current element of the sequence and advance the iterator to
     the next position.

     The WITH-ITER-PLACE macro can be used, within FORMS, both to
     retrieve and set the value of the current element of the
     sequence, and advance the iterator to the next position.

     NOTE: The value of the last form is not returned, due to it being
     evaluated in a TAGBODY, instead NIL is returned. RETURN-FROM, to
     an outer BLOCK, should be used to return a value from this form.

     NOTE: Whilst the intended use of WITH-ITERATORS is to implement
     iteration macros, such as DOSEQ, the FORMS are only evaluated
     once. It is up to the user to implement the actual loop, using
     the provided TAGBODY facility."

  (with-gensyms (end-tag)
    (labels ((expand-doseq (seq args body env)
               (-> (nth-form-type seq env)
                   (make-doseq seq args end-tag body env)
                   multiple-value-list))

             (make-form (bindings get-values places body)
               (->> (make-macros get-values places body)
                    (make-bindings bindings)))

             (make-macros (get-values places body)
               `(symbol-macrolet
                    ((iter-value-macros
                      ,(append get-values (iter-value-macros env)))

                     (iter-place-macros
                      ,(append places (iter-place-macros env))))

                  ,@body))

             ;; Tagbody

             (make-tagbody (body)
               `((tagbody
                    ,@body
                    ,end-tag)))


             ;; Bindings

             (make-bindings (bindings body)
               (loop
                  for binding in bindings
                  for (init constant?) = (multiple-value-list (make-binding binding))
                  if constant? collect init into constants
                  else collect init into vars
                  finally
                    (return
                      `(symbol-macrolet ,constants
                         (let* ,vars ,body)))))

             (make-binding (binding)
               (destructuring-bind (var init &key constant) binding
                 (if constant
                     (multiple-value-bind (value constant?)
                         (constant-form-value init env)

                       (values
                        `(,var ,value)
                        constant?))

                     (values
                      `(,var ,init)
                      nil)))))

      (loop
         for (var seq . args) in seqs
         for (bindings body value place) =
           (expand-doseq seq args (make-tagbody forms) env) then
           (expand-doseq seq args form-body env)

         for iter-value = (gensym "ITER-VALUE")
         for iter-place = (gensym "ITER-PLACE")
         for form-body = `((macrolet ((,iter-value ,@value)
                                      (,iter-place
                                          ,@(or place
                                                `((&rest args)
                                                  (declare (ignore args))
                                                  (error "In WITH-ITER-PLACE: Iterator ~s points to immutable sequence." ',var)))))
                             ,@body))

         append bindings into all-bindings
         collect (cons var iter-value) into get-values
         collect (cons var iter-place) into places

         finally
           (return
             (make-form all-bindings get-values places form-body))))))

Macroexpansion:
(symbol-macrolet nil (let* ((#:it165 (iterator seq1 :start start1 :end end1 :from-end from-end)) (#:it168 (iterator seq2 :start start2 :end end2 :from-end from-end))) (symbol-macrolet ((iter-value-macros ((it1 . #:iter-value166) (it2 . #:iter-value169))) (iter-place-macros ((it1 . #:iter-place167) (it2 . #:iter-place170)))) (macrolet ((#:iter-value169 (pattern &body body) (symbol-macrolet ((it (quote #:it168)) (tag (quote #:end-tag164))) (with-destructure-pattern (var pattern) (body decl body) (sb-int:quasiquote (progn (when (endp #S(sb-impl::comma :expr it :kind 0)) (go #S(sb-impl::comma :expr tag :kind 0))) (let ((#S(sb-impl::comma :expr var :kind 0) (at #S(sb-impl::comma :expr it :kind 0)))) #S(sb-impl::comma :expr decl :kind 2) (advance #S(sb-impl::comma :expr it :kind 0)) #S(sb-impl::comma :expr body :kind 2))))))) (#:iter-place170 (name more? &body body) (symbol-macrolet ((it (quote #:it168)) (tag (quote #:end-tag164))) (let ((body (sb-int:quasiquote (prog1 (progn #S(sb-impl::comma :expr body :kind 2)) (advance #S(sb-impl::comma :expr it :kind 0)))))) (with-variable-declarations ((decl-name name) (decl-more? more?)) forms body (sb-int:quasiquote (symbol-macrolet ((#S(sb-impl::comma :expr name :kind 0) (at #S(sb-impl::comma :expr it :kind 0)))) #S(sb-impl::comma :expr decl-name :kind 2) #S(sb-impl::comma :expr (if more? (sb-int:quasiquote (let ((#S(sb-impl::comma :expr more? :kind 0) (not (endp #S(sb-impl::comma :expr it :kind 0))))) #S(sb-impl::comma :expr decl-more? :kind 2) #S(sb-impl::comma :expr forms :kind 0))) (sb-int:quasiquote (progn (when (endp #S(sb-impl::comma :expr it :kind 0)) (go #S(sb-impl::comma :expr tag :kind 0))) #S(sb-impl::comma :expr forms :kind 0)))) :kind 0)))))))) (macrolet ((#:iter-value166 (pattern &body body) (symbol-macrolet ((it (quote #:it165)) (tag (quote #:end-tag164))) (with-destructure-pattern (var pattern) (body decl body) (sb-int:quasiquote (progn (when (endp #S(sb-impl::comma :expr it :kind 0)) (go #S(sb-impl::comma :expr tag :kind 0))) (let ((#S(sb-impl::comma :expr var :kind 0) (at #S(sb-impl::comma :expr it :kind 0)))) #S(sb-impl::comma :expr decl :kind 2) (advance #S(sb-impl::comma :expr it :kind 0)) #S(sb-impl::comma :expr body :kind 2))))))) (#:iter-place167 (name more? &body body) (symbol-macrolet ((it (quote #:it165)) (tag (quote #:end-tag164))) (let ((body (sb-int:quasiquote (prog1 (progn #S(sb-impl::comma :expr body :kind 2)) (advance #S(sb-impl::comma :expr it :kind 0)))))) (with-variable-declarations ((decl-name name) (decl-more? more?)) forms body (sb-int:quasiquote (symbol-macrolet ((#S(sb-impl::comma :expr name :kind 0) (at #S(sb-impl::comma :expr it :kind 0)))) #S(sb-impl::comma :expr decl-name :kind 2) #S(sb-impl::comma :expr (if more? (sb-int:quasiquote (let ((#S(sb-impl::comma :expr more? :kind 0) (not (endp #S(sb-impl::comma :expr it :kind 0))))) #S(sb-impl::comma :expr decl-more? :kind 2) #S(sb-impl::comma :expr forms :kind 0))) (sb-int:quasiquote (progn (when (endp #S(sb-impl::comma :expr it :kind 0)) (go #S(sb-impl::comma :expr tag :kind 0))) #S(sb-impl::comma :expr forms :kind 0)))) :kind 0)))))))) (tagbody (loop do (with-iter-place (e1 it1 more1?) (with-iter-place (e2 it2 more2?) (when (not (and more1? more2?)) (return-from mismatch (when (or more1? more2?) (compute-pos pos)))) (unless (funcall test (funcall key e1) (funcall key e2)) (return-from mismatch (compute-pos pos))) (incf pos)))) #:end-tag164))))))