backquote.el 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. ;; Copyright (C) 1985 Free Software Foundation, Inc.
  2. ;; Written by Dick King (king@kestrel).
  3. ;; This file is part of GNU Emacs.
  4. ;; GNU Emacs is distributed in the hope that it will be useful,
  5. ;; but WITHOUT ANY WARRANTY. No author or distributor
  6. ;; accepts responsibility to anyone for the consequences of using it
  7. ;; or for whether it serves any particular purpose or works at all,
  8. ;; unless he says so in writing. Refer to the GNU Emacs General Public
  9. ;; License for full details.
  10. ;; Everyone is granted permission to copy, modify and redistribute
  11. ;; GNU Emacs, but only under the conditions described in the
  12. ;; GNU Emacs General Public License. A copy of this license is
  13. ;; supposed to have been given to you along with GNU Emacs so you
  14. ;; can know your rights and responsibilities. It should be in a
  15. ;; file named COPYING. Among other things, the copyright notice
  16. ;; and this notice must be preserved on all copies.
  17. ;;; This is a rudimentry backquote package written by D. King,
  18. ;;; king@kestrel, on 8/31/85. (` x) is a macro
  19. ;;; that expands to a form that produces x. (` (a b ..)) is
  20. ;;; a macro that expands into a form that produces a list of what a b
  21. ;;; etc. would have produced. Any element can be of the form
  22. ;;; (, <form>) in which case the resulting form evaluates
  23. ;;; <form> before putting it into place, or (,@ <form>), in which
  24. ;;; case the evaluation of <form> is arranged for and each element
  25. ;;; of the result (which must be a (possibly null) list) is inserted.
  26. ;;; As an example, the immediately following macro push (v l) could
  27. ;;; have been written
  28. ;;; (defmacro push (v l)
  29. ;;; (` (setq (, l) (cons (,@ (list v l))))))
  30. ;;; although
  31. ;;; (defmacro push (v l)
  32. ;;; (` (setq (, l) (cons (, v) (, l)))))
  33. ;;; is far more natural. The magic atoms ,
  34. ;;; and ,@ are user-settable and list-valued. We recommend that
  35. ;;; things never be removed from this list lest you break something
  36. ;;; someone else wrote in the dim past that comes to be recompiled in
  37. ;;; the distant future.
  38. ;;; LIMITATIONS: tail consing is not handled correctly. Do not say
  39. ;;; (` (a . (, b))) - say (` (a (,@ b)))
  40. ;;; which works even if b is not list-valued.
  41. ;;; No attempt is made to handle vectors. (` [a (, b) c]) doesn't work.
  42. ;;; Sorry, you must say things like
  43. ;;; (` (a (,@ 'b))) to get (a . b) and
  44. ;;; (` ((, ',) c)) to get (, c) - [(` (a , b)) will work but is a bad habit]
  45. ;;; I haven't taught it the joys of nconc.
  46. ;;; (` atom) dies. (` (, atom)) or anything else is okay.
  47. ;;; BEWARE BEWARE BEWARE
  48. ;;; inclusion of (,atom) rather than (, atom) or (,@atom) rather than
  49. ;;; (,@ atom) will result in errors that will show up very late.
  50. ;;; This is so crunchy that I am considering including a check for
  51. ;;; this or changing the syntax to ... ,(<form>). RMS: opinion?
  52. (provide 'backquote)
  53. ;;; a raft of general-purpose macros follows. See the nearest
  54. ;;; Commonlisp manual.
  55. (defmacro push (v l)
  56. "Pushes evaluated first form onto second unevaluated object
  57. a list-value atom"
  58. (list 'setq l (list 'cons v l)))
  59. (defmacro caar (l)
  60. (list 'car (list 'car l)))
  61. (defmacro cadr (l)
  62. (list 'car (list 'cdr l)))
  63. (defmacro cdar (l)
  64. (list 'cdr (list 'car l)))
  65. (defmacro cddr (l)
  66. (list 'cdr (list 'cdr l)))
  67. ;;; These two advertised variables control what characters are used to
  68. ;;; unquote things. I have included , and ,@ as the unquote and
  69. ;;; splice operators, respectively, to give users of MIT CADR machine
  70. ;;; derivitive machines a warm, cosy feeling.
  71. (defconst backquote-unquote '(,)
  72. "*A list of all objects that stimulate unquoting in `. Memq test.")
  73. (defconst backquote-splice '(,@)
  74. "*A list of all objects that stimulate splicing in `. Memq test.")
  75. ;;; This is the interface
  76. (defmacro ` (form)
  77. "(` FORM) Expands to a form that will generate FORM.
  78. FORM is `almost quoted' -- see backquote.el for a description."
  79. (bq-make-maker form))
  80. ;;; We develop the method for building the desired list from
  81. ;;; the end towards the beginning. The contract is that there be a
  82. ;;; variable called state and a list called tailmaker, and that the form
  83. ;;; (cons state tailmaker) deliver the goods. Exception - if the
  84. ;;; state is quote the tailmaker is the form itself.
  85. ;;; This function takes a form and returns what I will call a maker in
  86. ;;; what follows. Evaluating the maker would produce the form,
  87. ;;; properly evaluated according to , and ,@ rules.
  88. ;;; I work backwards - it seemed a lot easier. The reason for this is
  89. ;;; if I'm in some sort of a routine building a maker and I switch
  90. ;;; gears, it seemed to me easier to jump into some other state and
  91. ;;; glue what I've already done to the end, than to to prepare that
  92. ;;; something and go back to put things together.
  93. (defun bq-make-maker (form)
  94. "Given one argument, a `mostly quoted' object, produces a maker.
  95. See backquote.el for details"
  96. (let ((tailmaker (quote nil)) (qc 0) (ec 0) (state nil))
  97. (mapcar 'bq-iterative-list-builder (reverse form))
  98. (and state
  99. (cond ((eq state 'quote)
  100. (list state tailmaker))
  101. ((= (length tailmaker) 1)
  102. (funcall (cadr (assq state bq-singles)) tailmaker))
  103. (t (cons state tailmaker))))))
  104. ;;; There are exceptions - we wouldn't want to call append of one
  105. ;;; argument, for example.
  106. (defconst bq-singles '((quote bq-quotecar)
  107. (append car)
  108. (list bq-make-list)
  109. (cons bq-id)))
  110. (defun bq-id (x) x)
  111. (defun bq-quotecar (x) (list 'quote (car x)))
  112. (defun bq-make-list (x) (cons 'list x))
  113. ;;; fr debugging use only
  114. ;(defun funcalll (a b) (funcall a b))
  115. ;(defun funcalll (a b) (debug nil 'enter state tailmaker a b)
  116. ; (let ((ans (funcall a b))) (debug nil 'leave state tailmaker)
  117. ; ans))
  118. ;;; Given a state/tailmaker pair that already knows how to make a
  119. ;;; partial tail of the desired form, this function knows how to add
  120. ;;; yet another element to the burgening list. There are four cases;
  121. ;;; the next item is an atom (which will certainly be quoted); a
  122. ;;; (, xxx), which will be evaluated and put into the list at the top
  123. ;;; level; a (,@ xxx), which will be evaluated and spliced in, or
  124. ;;; some other list, in which case we first compute the form's maker,
  125. ;;; and then we either launch into the quoted case if the maker's
  126. ;;; top level function is quote, or into the comma case if it isn't.
  127. ;;; The fourth case reduces to one of the other three, so here we have
  128. ;;; a choice of three ways to build tailmaker, and cit turns out we
  129. ;;; use five possible values of state (although someday I'll add
  130. ;;; nconcto the possible values of state).
  131. ;;; This maintains the invariant that (cons state tailmaker) is the
  132. ;;; maker for the elements of the tail we've eaten so far.
  133. (defun bq-iterative-list-builder (form)
  134. "Called by bq-make-maker. Adds a new item form to tailmaker,
  135. changing state if need be, so tailmaker and state constitute a recipie
  136. for making the list so far."
  137. (cond ((atom form)
  138. (funcall (cadr (assq state bq-quotefns)) form))
  139. ((memq (car form) backquote-unquote)
  140. (funcall (cadr (assq state bq-evalfns)) (cadr form)))
  141. ((memq (car form) backquote-splice)
  142. (funcall (cadr (assq state bq-splicefns)) (cadr form)))
  143. (t
  144. (let ((newform (bq-make-maker form)))
  145. (if (and (listp newform) (eq (car newform) 'quote))
  146. (funcall (cadr (assq state bq-quotefns)) (cadr newform))
  147. (funcall (cadr (assq state bq-evalfns)) newform))))
  148. ))
  149. ;;; We do a 2-d branch on the form of splicing and the old state.
  150. ;;; Here's fifteen functions' names...
  151. (defconst bq-splicefns '((nil bq-splicenil)
  152. (append bq-spliceappend)
  153. (list bq-splicelist)
  154. (quote bq-splicequote)
  155. (cons bq-splicecons)))
  156. (defconst bq-evalfns '((nil bq-evalnil)
  157. (append bq-evalappend)
  158. (list bq-evallist)
  159. (quote bq-evalquote)
  160. (cons bq-evalcons)))
  161. (defconst bq-quotefns '((nil bq-quotenil)
  162. (append bq-quoteappend)
  163. (list bq-quotelist)
  164. (quote bq-quotequote)
  165. (cons bq-quotecons)))
  166. ;;; The name of each function is
  167. ;;; (concat 'bq- <type-of-element-addition> <old-state>)
  168. ;;; I'll comment the non-obvious ones before the definitions...
  169. ;;; In what follows, uppercase letters and form will always be
  170. ;;; metavariables that don't need commas in backquotes, and I will
  171. ;;; assume the existence of something like matches that takes a
  172. ;;; backquote-like form and a value, binds metavariables and returns
  173. ;;; t if the pattern match is successful, returns nil otherwise. I
  174. ;;; will write such a goodie someday.
  175. ;;; (setq tailmaker
  176. ;;; (if (matches ((quote X) Y) tailmaker)
  177. ;;; (` ((quote (form X)) Y))
  178. ;;; (` ((list form (quote X)) Y))))
  179. ;;; (setq state 'append)
  180. (defun bq-quotecons (form)
  181. (if (and (listp (car tailmaker))
  182. (eq (caar tailmaker) 'quote))
  183. (setq tailmaker
  184. (list (list 'quote (list form (cadr (car tailmaker))))
  185. (cadr tailmaker)))
  186. (setq tailmaker
  187. (list (list 'list
  188. (list 'quote form)
  189. (car tailmaker))
  190. (cadr tailmaker))))
  191. (setq state 'append))
  192. (defun bq-quotequote (form)
  193. (push form tailmaker))
  194. ;;; Could be improved to convert (list 'a 'b 'c .. 'w x)
  195. ;;; to (append '(a b c .. w) x)
  196. ;;; when there are enough elements
  197. (defun bq-quotelist (form)
  198. (push (list 'quote form) tailmaker))
  199. ;;; (setq tailmaker
  200. ;;; (if (matches ((quote X) (,@ Y)))
  201. ;;; (` ((quote (, (cons form X))) (,@ Y)))))
  202. (defun bq-quoteappend (form)
  203. (cond ((and (listp tailmaker)
  204. (listp (car tailmaker))
  205. (eq (caar tailmaker) 'quote))
  206. (rplaca (cdar tailmaker)
  207. (cons form (car (cdar tailmaker)))))
  208. (t (push (list 'quote (list form)) tailmaker))))
  209. (defun bq-quotenil (form)
  210. (setq tailmaker (list form))
  211. (setq state 'quote))
  212. ;;; (if (matches (X Y) tailmaker) ; it must
  213. ;;; (` ((list form X) Y)))
  214. (defun bq-evalcons (form)
  215. (setq tailmaker
  216. (list (list 'list form (car tailmaker))
  217. (cadr tailmaker)))
  218. (setq state 'append))
  219. ;;; (if (matches (X Y Z (,@ W)))
  220. ;;; (progn (setq state 'append)
  221. ;;; (` ((list form) (quote (X Y Z (,@ W))))))
  222. ;;; (progn (setq state 'list)
  223. ;;; (list form 'X 'Y .. ))) ; quote each one there is
  224. (defun bq-evalquote (form)
  225. (cond ((< (length tailmaker) 3)
  226. (setq tailmaker
  227. (cons form
  228. (mapcar (function (lambda (x)
  229. (list 'quote x)))
  230. tailmaker)))
  231. (setq state 'list))
  232. (t
  233. (setq tailmaker
  234. (list (list 'list form)
  235. (list 'quote tailmaker)))
  236. (setq state 'append))))
  237. (defun bq-evallist (form)
  238. (push form tailmaker))
  239. ;;; (cond ((matches ((list (,@ X)) (,@ Y)))
  240. ;;; (` ((list form (,@ X)) (,@ Y))))
  241. ;;; ((matches (X))
  242. ;;; (` (form (,@ X))) (setq state 'cons))
  243. ;;; ((matches ((,@ X)))
  244. ;;; (` (form (,@ X)))))
  245. (defun bq-evalappend (form)
  246. (cond ((and (listp tailmaker)
  247. (listp (car tailmaker))
  248. (eq (caar tailmaker) 'list))
  249. (rplacd (car tailmaker)
  250. (cons form (cdar tailmaker))))
  251. ((= (length tailmaker) 1)
  252. (setq tailmaker (cons form tailmaker))
  253. (setq state 'cons))
  254. (t (push (list 'list form) tailmaker))))
  255. (defun bq-evalnil (form)
  256. (setq tailmaker (list form))
  257. (setq state 'list))
  258. ;;; (if (matches (X Y)) ; it must
  259. ;;; (progn (setq state 'append)
  260. ;;; (` (form (cons X Y))))) ; couldn't think of anything clever
  261. (defun bq-splicecons (form)
  262. (setq tailmaker
  263. (list form
  264. (list 'cons (car tailmaker) (cadr tailmaker))))
  265. (setq state 'append))
  266. (defun bq-splicequote (form)
  267. (setq tailmaker (list form (list 'quote (list tailmaker))))
  268. (setq state 'append))
  269. (defun bq-splicelist (form)
  270. (setq tailmaker (list form (cons 'list tailmaker)))
  271. (setq state 'append))
  272. (defun bq-spliceappend (form)
  273. (push form tailmaker))
  274. (defun bq-splicenil (form)
  275. (setq state 'append)
  276. (setq tailmaker (list form)))