diff options
| author | Stefan Monnier | 2007-08-10 06:52:30 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2007-08-10 06:52:30 +0000 |
| commit | 3527bdcc4375b6991fc986d83fb5fc0203254ce8 (patch) | |
| tree | 0673d8b2bbc76986a108b94530aee1f0afeb61cb | |
| parent | 33e5d7d4c9998782b15081248e49b951725ed5f3 (diff) | |
| download | emacs-3527bdcc4375b6991fc986d83fb5fc0203254ce8.tar.gz emacs-3527bdcc4375b6991fc986d83fb5fc0203254ce8.zip | |
(backquote-delay-process): New function.
(backquote-process): Add internal arg `level'. Use the two to
correctly handle nested backquotes.
| -rw-r--r-- | lisp/emacs-lisp/backquote.el | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/lisp/emacs-lisp/backquote.el b/lisp/emacs-lisp/backquote.el index 54fcfc3df8a..6daaf001433 100644 --- a/lisp/emacs-lisp/backquote.el +++ b/lisp/emacs-lisp/backquote.el | |||
| @@ -118,10 +118,28 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 118 | ;; constant, 1 => to be unquoted, 2 => to be spliced in. | 118 | ;; constant, 1 => to be unquoted, 2 => to be spliced in. |
| 119 | ;; The top-level backquote macro just discards the tag. | 119 | ;; The top-level backquote macro just discards the tag. |
| 120 | 120 | ||
| 121 | (defun backquote-process (s) | 121 | (defun backquote-delay-process (s level) |
| 122 | "Process a (un|back|splice)quote inside a backquote. | ||
| 123 | This simply recurses through the body." | ||
| 124 | (let ((exp (backquote-listify (list (backquote-process (nth 1 s) level) | ||
| 125 | (cons 0 (list 'quote (car s)))) | ||
| 126 | '(0)))) | ||
| 127 | (if (eq (car-safe exp) 'quote) | ||
| 128 | (cons 0 (list 'quote s)) | ||
| 129 | (cons 1 exp)))) | ||
| 130 | |||
| 131 | (defun backquote-process (s &optional level) | ||
| 132 | "Process the body of a backquote. | ||
| 133 | S is the body. Returns a cons cell whose cdr is piece of code which | ||
| 134 | is the macro-expansion of S, and whose car is a small integer whose value | ||
| 135 | can either indicate that the code is constant (0), or not (1), or returns | ||
| 136 | a list which should be spliced into its environment (2). | ||
| 137 | LEVEL is only used internally and indicates the nesting level: | ||
| 138 | 0 (the default) is for the toplevel nested inside a single backquote." | ||
| 139 | (unless level (setq level 0)) | ||
| 122 | (cond | 140 | (cond |
| 123 | ((vectorp s) | 141 | ((vectorp s) |
| 124 | (let ((n (backquote-process (append s ())))) | 142 | (let ((n (backquote-process (append s ()) level))) |
| 125 | (if (= (car n) 0) | 143 | (if (= (car n) 0) |
| 126 | (cons 0 s) | 144 | (cons 0 s) |
| 127 | (cons 1 (cond | 145 | (cons 1 (cond |
| @@ -138,11 +156,15 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 138 | s | 156 | s |
| 139 | (list 'quote s)))) | 157 | (list 'quote s)))) |
| 140 | ((eq (car s) backquote-unquote-symbol) | 158 | ((eq (car s) backquote-unquote-symbol) |
| 141 | (cons 1 (nth 1 s))) | 159 | (if (<= level 0) |
| 160 | (cons 1 (nth 1 s)) | ||
| 161 | (backquote-delay-process s (1- level)))) | ||
| 142 | ((eq (car s) backquote-splice-symbol) | 162 | ((eq (car s) backquote-splice-symbol) |
| 143 | (cons 2 (nth 1 s))) | 163 | (if (<= level 0) |
| 164 | (cons 2 (nth 1 s)) | ||
| 165 | (backquote-delay-process s (1- level)))) | ||
| 144 | ((eq (car s) backquote-backquote-symbol) | 166 | ((eq (car s) backquote-backquote-symbol) |
| 145 | (backquote-process (cdr (backquote-process (nth 1 s))))) | 167 | (backquote-delay-process s (1+ level))) |
| 146 | (t | 168 | (t |
| 147 | (let ((rest s) | 169 | (let ((rest s) |
| 148 | item firstlist list lists expression) | 170 | item firstlist list lists expression) |
| @@ -154,11 +176,13 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 154 | ;; at the beginning, put them in FIRSTLIST, | 176 | ;; at the beginning, put them in FIRSTLIST, |
| 155 | ;; as a list of tagged values (TAG . FORM). | 177 | ;; as a list of tagged values (TAG . FORM). |
| 156 | ;; If there are any at the end, they go in LIST, likewise. | 178 | ;; If there are any at the end, they go in LIST, likewise. |
| 157 | (while (consp rest) | 179 | (while (and (consp rest) |
| 158 | ;; Turn . (, foo) into (,@ foo). | 180 | ;; Stop if the cdr is an expression inside a backquote or |
| 159 | (if (eq (car rest) backquote-unquote-symbol) | 181 | ;; unquote since this needs to go recursively through |
| 160 | (setq rest (list (list backquote-splice-symbol (nth 1 rest))))) | 182 | ;; backquote-process. |
| 161 | (setq item (backquote-process (car rest))) | 183 | (not (or (eq (car rest) backquote-unquote-symbol) |
| 184 | (eq (car rest) backquote-backquote-symbol)))) | ||
| 185 | (setq item (backquote-process (car rest) level)) | ||
| 162 | (cond | 186 | (cond |
| 163 | ((= (car item) 2) | 187 | ((= (car item) 2) |
| 164 | ;; Put the nonspliced items before the first spliced item | 188 | ;; Put the nonspliced items before the first spliced item |
| @@ -168,8 +192,8 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 168 | list nil)) | 192 | list nil)) |
| 169 | ;; Otherwise, put any preceding nonspliced items into LISTS. | 193 | ;; Otherwise, put any preceding nonspliced items into LISTS. |
| 170 | (if list | 194 | (if list |
| 171 | (setq lists (cons (backquote-listify list '(0 . nil)) lists))) | 195 | (push (backquote-listify list '(0 . nil)) lists)) |
| 172 | (setq lists (cons (cdr item) lists)) | 196 | (push (cdr item) lists) |
| 173 | (setq list nil)) | 197 | (setq list nil)) |
| 174 | (t | 198 | (t |
| 175 | (setq list (cons item list)))) | 199 | (setq list (cons item list)))) |
| @@ -177,8 +201,8 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 177 | ;; Handle nonsplicing final elements, and the tail of the list | 201 | ;; Handle nonsplicing final elements, and the tail of the list |
| 178 | ;; (which remains in REST). | 202 | ;; (which remains in REST). |
| 179 | (if (or rest list) | 203 | (if (or rest list) |
| 180 | (setq lists (cons (backquote-listify list (backquote-process rest)) | 204 | (push (backquote-listify list (backquote-process rest level)) |
| 181 | lists))) | 205 | lists)) |
| 182 | ;; Turn LISTS into a form that produces the combined list. | 206 | ;; Turn LISTS into a form that produces the combined list. |
| 183 | (setq expression | 207 | (setq expression |
| 184 | (if (or (cdr lists) | 208 | (if (or (cdr lists) |
| @@ -221,5 +245,5 @@ Vectors work just like lists. Nested backquotes are permitted." | |||
| 221 | tail)) | 245 | tail)) |
| 222 | (t (cons 'list heads))))) | 246 | (t (cons 'list heads))))) |
| 223 | 247 | ||
| 224 | ;;; arch-tag: 1a26206a-6b5e-4c56-8e24-2eef0f7e0e7a | 248 | ;; arch-tag: 1a26206a-6b5e-4c56-8e24-2eef0f7e0e7a |
| 225 | ;;; backquote.el ends here | 249 | ;;; backquote.el ends here |