Create a Common Lisp macro for the following transformation. Before code:
(jbind string "hello" string)

What needs to change: Macro call that should be transformed by jbind

Macro definition:
(defmacro jbind (destructuring-pattern form &body body)
  "Match the FORM against DESTRUCTURING-PATTERN.
The pattern might be:
- A symbol, in which case the current chosen form is bound to it. If
  the symbol is _, simply skip the form.
- A literal form:
  - String or number: compare with `equal'.
  - Keywords :TRUE, :FALSE, and :NULL, matching T, NIL, and :NULL
    respectively.
- If the pattern is a property list of string+pattern pairs, match the
  string+pattern pairs inside it to the provided JSON object and
  resolve them recursively.
- If the pattern is a list of symbols (VAR &optional VAR-P), these are
  bound to the respective values of `jget'. It is a good way to make
  `jbind' to be more lenient to missing keys, because the default
  behavior is to error on missing data.
- If the pattern is an inline vector, match it against a JSON array
  with at least as many elements as provided in the vector. Match
  every form in the vector against the element with the same index.

If the DESTRUCTURING-PATTERN doesn't match the object, throw
`value-mismatch'.

Underlying `jget' can throw errors for the exceptionally malformed
inputs. See `jget' documentation for the types of errors it throws.

Example:
\(\"hello\" hello \"a\" _ \"b\" b
 \"array\" #(first second third _))

matches a JSON object
{\"hello\": 3, \"a\": 8, \"b\": 3, \"c\": null, \"array\": [1, 2, 3, 4]}

and binds
- HELLO to 3
- B to 3
- FIRST to 1
- SECOND to 2
- THIRD to 3

It also checks that \"a\" key is present in the object and there's a
fourth element in the nested array.

See more examples in njson tests."
  (let ((form-sym (gensym "BIND-FORM"))
        (bindings (list)))
    (labels ((parse-pattern (pattern &optional (current-path (list)))
               (etypecase pattern
                 ((or (member :true :false :null) string real)
                  (push (cons pattern (copy-list current-path))
                        bindings))
                 ((cons symbol *)
                  (push (cons pattern (copy-list current-path))
                        bindings))
                 (list
                  (loop for (key subpattern) on pattern by #'cddr
                        do (parse-pattern subpattern (append current-path (list key))))
                  (push (cons nil (copy-list current-path))
                        bindings))
                 ((and symbol (not keyword))
                  (push (cons (if (equal "_" (symbol-name pattern))
                                  (gensym "_PATTERN")
                                  pattern)
                              (copy-list current-path))
                        bindings))
                 (array
		  (loop for elem across pattern
                        for index from 0
                        do (parse-pattern elem (append current-path (list index))))
		  (push (cons #() (copy-list current-path))
			bindings)))))
      (check-type destructuring-pattern (or list (and array (not string))
                                            (and symbol (not keyword)))
                  "proper jbind destructuring pattern: list, array, or symbol")
      (parse-pattern destructuring-pattern)
      (let ((let-forms (loop for (binding . key) in bindings
                             do (check-type binding (or array real symbol
                                                        ;; For (VAR VAR-P) forms
                                                        (cons symbol (or (cons symbol null)
                                                                         null))))
                             if (typep binding '(or array real null
                                                 (member :true :false :null)))
                               collect `(,(gensym) (check-value ,binding (vector ,@key) ,form-sym))
                             else if (and (symbolp binding)
                                          (uiop:emptyp key))
                                    collect `(,binding ,form-sym)
                             else if (listp binding)
                                    append (destructuring-bind (var &optional (var-p nil var-p-provided))
                                               binding
                                             (append
                                              `((,var (jget (vector ,@key) ,form-sym)))
                                              (when var-p-provided
                                                `((,var-p (nth-value 1 (jget (vector ,@key) ,form-sym)))))))
                             else
                               collect `(,binding (check-value t (vector ,@key) ,form-sym)))))
        `(let* ((,form-sym ,form)
                ,@let-forms)
           (declare (ignorable ,form-sym ,@(mapcar #'first let-forms)))
           ,@body))))

Macroexpansion:
(let* ((#:bind-form127 "hello") (string #:bind-form127)) (declare (ignorable #:bind-form127 string)) string)