aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2007-08-10 06:52:30 +0000
committerStefan Monnier2007-08-10 06:52:30 +0000
commit3527bdcc4375b6991fc986d83fb5fc0203254ce8 (patch)
tree0673d8b2bbc76986a108b94530aee1f0afeb61cb
parent33e5d7d4c9998782b15081248e49b951725ed5f3 (diff)
downloademacs-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.el54
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.
123This 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.
133S is the body. Returns a cons cell whose cdr is piece of code which
134is the macro-expansion of S, and whose car is a small integer whose value
135can either indicate that the code is constant (0), or not (1), or returns
136a list which should be spliced into its environment (2).
137LEVEL is only used internally and indicates the nesting level:
1380 (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