Mercurial > hg > xemacs-beta
comparison lisp/cl-macs.el @ 5118:e0db3c197671 ben-lisp-object
merge up to latest default branch, doesn't compile yet
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Sat, 26 Dec 2009 21:18:49 -0600 |
parents | e29fcfd8df5f |
children | 95b04754ea8c 8b50bee3c88c |
comparison
equal
deleted
inserted
replaced
5117:3742ea8250b5 | 5118:e0db3c197671 |
---|---|
273 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) | 273 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) |
274 | 274 |
275 (defvar cl-macro-environment nil) | 275 (defvar cl-macro-environment nil) |
276 (defvar bind-block) (defvar bind-defs) (defvar bind-enquote) | 276 (defvar bind-block) (defvar bind-defs) (defvar bind-enquote) |
277 (defvar bind-inits) (defvar bind-lets) (defvar bind-forms) | 277 (defvar bind-inits) (defvar bind-lets) (defvar bind-forms) |
278 (defvar arglist-visited) | |
279 | 278 |
280 ;; npak@ispras.ru | 279 ;; npak@ispras.ru |
281 (defun cl-upcase-arg (arg) | 280 (defun cl-upcase-arg (arg) |
282 ;; Changes all non-keyword symbols in `ARG' to symbols | 281 ;; Changes all non-keyword symbols in `ARG' to symbols |
283 ;; with name in upper case. | 282 ;; with name in upper case. |
284 ;; ARG is either symbol or list of symbols or lists | 283 ;; ARG is either symbol or list of symbols or lists |
285 (cond ((symbolp arg) | 284 (cond ((symbolp arg) |
286 ;; Do not upcase &optional, &key etc. | 285 ;; Do not upcase &optional, &key etc. |
287 (if (memq arg lambda-list-keywords) arg | 286 (if (memq arg lambda-list-keywords) |
288 (intern (upcase (symbol-name arg))))) | 287 arg |
288 (make-symbol (upcase (symbol-name arg))))) | |
289 ((listp arg) | 289 ((listp arg) |
290 (if (memq arg arglist-visited) (error 'circular-list '(arg))) | |
291 (push arg arglist-visited) | |
292 (let ((arg (copy-list arg)) junk) | 290 (let ((arg (copy-list arg)) junk) |
293 ;; Clean the list | 291 ;; Clean the list |
294 (let ((p (last arg))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) | 292 (let ((p (last arg))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) |
295 (if (setq junk (cadr (memq '&cl-defs arg))) | 293 (if (setq junk (cadr (memq '&cl-defs arg))) |
296 (setq arg (delq '&cl-defs (delq junk arg)))) | 294 (setq arg (delq '&cl-defs (delq junk arg)))) |
298 (setq arg (delq '&cl-quote arg))) | 296 (setq arg (delq '&cl-quote arg))) |
299 (mapcar 'cl-upcase-arg arg))) | 297 (mapcar 'cl-upcase-arg arg))) |
300 (t arg))) ; Maybe we are in initializer | 298 (t arg))) ; Maybe we are in initializer |
301 | 299 |
302 ;; npak@ispras.ru | 300 ;; npak@ispras.ru |
301 ;;;###autoload | |
303 (defun cl-function-arglist (name arglist) | 302 (defun cl-function-arglist (name arglist) |
304 "Returns string with printed representation of arguments list. | 303 "Returns string with printed representation of arguments list. |
305 Supports Common Lisp lambda lists." | 304 Supports Common Lisp lambda lists." |
306 (if (not (or (listp arglist) (symbolp arglist))) | 305 (if (not (or (listp arglist) (symbolp arglist))) |
307 "Not available" | 306 "Not available" |
308 (setq arglist-visited nil) | 307 (check-argument-type #'true-list-p arglist) |
309 (condition-case nil | 308 (let ((print-gensym nil)) |
310 (prin1-to-string | 309 (condition-case nil |
311 (cons (if (eq name 'cl-none) 'lambda name) | 310 (prin1-to-string |
312 (cond ((null arglist) nil) | 311 (cons (if (eq name 'cl-none) 'lambda name) |
313 ((listp arglist) (cl-upcase-arg arglist)) | 312 (cond ((null arglist) nil) |
314 ((symbolp arglist) | 313 ((listp arglist) (cl-upcase-arg arglist)) |
315 (cl-upcase-arg (list '&rest arglist))) | 314 ((symbolp arglist) |
316 (t (wrong-type-argument 'listp arglist))))) | 315 (cl-upcase-arg (list '&rest arglist))) |
317 (t "Not available")))) | 316 (t (wrong-type-argument 'listp arglist))))) |
318 | 317 (t "Not available"))))) |
319 | 318 |
320 (defun cl-transform-lambda (form bind-block) | 319 (defun cl-transform-lambda (form bind-block) |
321 (let* ((args (car form)) (body (cdr form)) | 320 (let* ((args (car form)) (body (cdr form)) |
322 (bind-defs nil) (bind-enquote nil) | 321 (bind-defs nil) (bind-enquote nil) |
323 (bind-inits nil) (bind-lets nil) (bind-forms nil) | 322 (bind-inits nil) (bind-lets nil) (bind-forms nil) |
324 (header nil) (simple-args nil) | 323 (header nil) (simple-args nil) |
324 (complex-arglist (cl-function-arglist bind-block args)) | |
325 (doc "")) | 325 (doc "")) |
326 ;; Add CL lambda list to documentation. npak@ispras.ru | |
327 (if (and (stringp (car body)) | |
328 (cdr body)) | |
329 (setq doc (pop body))) | |
330 (push (concat doc | |
331 "\nCommon Lisp lambda list:\n" | |
332 " " (cl-function-arglist bind-block args) | |
333 "\n\n") | |
334 header) | |
335 | |
336 (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) | 326 (while (or (stringp (car body)) (eq (car-safe (car body)) 'interactive)) |
337 (push (pop body) header)) | 327 (push (pop body) header)) |
338 (setq args (if (listp args) (copy-list args) (list '&rest args))) | 328 (setq args (if (listp args) (copy-list args) (list '&rest args))) |
339 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) | 329 (let ((p (last args))) (if (cdr p) (setcdr p (list '&rest (cdr p))))) |
340 (if (setq bind-defs (cadr (memq '&cl-defs args))) | 330 (if (setq bind-defs (cadr (memq '&cl-defs args))) |
351 (not (and (eq (car args) '&optional) | 341 (not (and (eq (car args) '&optional) |
352 (or bind-defs (consp (cadr args)))))) | 342 (or bind-defs (consp (cadr args)))))) |
353 (push (pop args) simple-args)) | 343 (push (pop args) simple-args)) |
354 (or (eq bind-block 'cl-none) | 344 (or (eq bind-block 'cl-none) |
355 (setq body (list (list* 'block bind-block body)))) | 345 (setq body (list (list* 'block bind-block body)))) |
346 (setq simple-args (nreverse simple-args) | |
347 header (nreverse header)) | |
348 ;; Add CL lambda list to documentation, if the CL lambda list differs | |
349 ;; from the non-CL lambda list. npak@ispras.ru | |
350 (unless (equal complex-arglist | |
351 (cl-function-arglist bind-block simple-args)) | |
352 (and (stringp (car header)) (setq doc (pop header))) | |
353 (push (concat doc | |
354 "\n\nCommon Lisp lambda list:\n" | |
355 " " complex-arglist "\n\n") | |
356 header)) | |
356 (if (null args) | 357 (if (null args) |
357 (list* nil (nreverse simple-args) (nconc (nreverse header) body)) | 358 (list* nil simple-args (nconc header body)) |
358 (if (memq '&optional simple-args) (push '&optional args)) | 359 (if (memq '&optional simple-args) (push '&optional args)) |
359 (cl-do-arglist args nil (- (length simple-args) | 360 (cl-do-arglist args nil (- (length simple-args) |
360 (if (memq '&optional simple-args) 1 0))) | 361 (if (memq '&optional simple-args) 1 0))) |
361 (setq bind-lets (nreverse bind-lets)) | 362 (setq bind-lets (nreverse bind-lets)) |
362 (list* (and bind-inits (list* 'eval-when '(compile load eval) | 363 (list* (and bind-inits (list* 'eval-when '(compile load eval) |
363 (nreverse bind-inits))) | 364 (nreverse bind-inits))) |
364 (nconc (nreverse simple-args) | 365 (nconc simple-args |
365 (list '&rest (car (pop bind-lets)))) | 366 (list '&rest (car (pop bind-lets)))) |
366 ;; XEmacs change: we add usage information using Nickolay's | 367 ;; XEmacs change: we add usage information using Nickolay's |
367 ;; approach above | 368 ;; approach above |
368 (nconc (nreverse header) | 369 (nconc header |
369 (list (nconc (list 'let* bind-lets) | 370 (list (nconc (list 'let* bind-lets) |
370 (nreverse bind-forms) body))))))) | 371 (nreverse bind-forms) body))))))) |
371 | 372 |
372 (defun cl-do-arglist (args expr &optional num) ; uses bind-* | 373 (defun cl-do-arglist (args expr &optional num) ; uses bind-* |
373 (if (nlistp args) | 374 (if (nlistp args) |
608 | 609 |
609 ;;; Conditional control structures. | 610 ;;; Conditional control structures. |
610 | 611 |
611 ;;;###autoload | 612 ;;;###autoload |
612 (defmacro case (expr &rest clauses) | 613 (defmacro case (expr &rest clauses) |
613 "(case EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. | 614 "Evals EXPR, chooses from CLAUSES on that value. |
614 Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared | 615 Each clause looks like (KEYLIST BODY...). EXPR is evaluated and compared |
615 against each key in each KEYLIST; the corresponding BODY is evaluated. | 616 against each key in each KEYLIST; the corresponding BODY is evaluated. |
616 If no clause succeeds, case returns nil. A single atom may be used in | 617 If no clause succeeds, case returns nil. A single atom may be used in |
617 place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is | 618 place of a KEYLIST of one atom. A KEYLIST of `t' or `otherwise' is |
618 allowed only in the final clause, and matches if no other keys match. | 619 allowed only in the final clause, and matches if no other keys match. |
653 ;; anything to introduce it, as there is probably much more CL stuff | 654 ;; anything to introduce it, as there is probably much more CL stuff |
654 ;; missing, and the feature is not essential. --hniksic | 655 ;; missing, and the feature is not essential. --hniksic |
655 | 656 |
656 ;;;###autoload | 657 ;;;###autoload |
657 (defmacro ecase (expr &rest clauses) | 658 (defmacro ecase (expr &rest clauses) |
658 "(ecase EXPR CLAUSES...): like `case', but error if no case fits. | 659 "Like `case', but error if no case fits. |
659 `otherwise'-clauses are not allowed." | 660 `otherwise'-clauses are not allowed." |
660 ;; XEmacs addition: disallow t and otherwise | 661 ;; XEmacs addition: disallow t and otherwise |
661 (let ((disallowed (or (assq t clauses) | 662 (let ((disallowed (or (assq t clauses) |
662 (assq 'otherwise clauses)))) | 663 (assq 'otherwise clauses)))) |
663 (if disallowed | 664 (if disallowed |
664 (error "`%s' is not allowed in ecase" (car disallowed)))) | 665 (error "`%s' is not allowed in ecase" (car disallowed)))) |
665 (list* 'case expr (append clauses '((ecase-error-flag))))) | 666 (list* 'case expr (append clauses '((ecase-error-flag))))) |
666 | 667 |
667 ;;;###autoload | 668 ;;;###autoload |
668 (defmacro typecase (expr &rest clauses) | 669 (defmacro typecase (expr &rest clauses) |
669 "(typecase EXPR CLAUSES...): evals EXPR, chooses from CLAUSES on that value. | 670 "Evals EXPR, chooses from CLAUSES on that value. |
670 Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it | 671 Each clause looks like (TYPE BODY...). EXPR is evaluated and, if it |
671 satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, | 672 satisfies TYPE, the corresponding BODY is evaluated. If no clause succeeds, |
672 typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the | 673 typecase returns nil. A TYPE of `t' or `otherwise' is allowed only in the |
673 final clause, and matches if no other keys match." | 674 final clause, and matches if no other keys match." |
674 (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) | 675 (let* ((temp (if (cl-simple-expr-p expr 3) expr (gensym))) |
689 (if (eq temp expr) body | 690 (if (eq temp expr) body |
690 (list 'let (list (list temp expr)) body)))) | 691 (list 'let (list (list temp expr)) body)))) |
691 | 692 |
692 ;;;###autoload | 693 ;;;###autoload |
693 (defmacro etypecase (expr &rest clauses) | 694 (defmacro etypecase (expr &rest clauses) |
694 "(etypecase EXPR CLAUSES...): like `typecase', but error if no case fits. | 695 "Like `typecase', but error if no case fits. |
695 `otherwise'-clauses are not allowed." | 696 `otherwise'-clauses are not allowed." |
696 (list* 'typecase expr (append clauses '((ecase-error-flag))))) | 697 (list* 'typecase expr (append clauses '((ecase-error-flag))))) |
697 | 698 |
698 | 699 |
699 ;;; Blocks and exits. | 700 ;;; Blocks and exits. |
700 | 701 |
701 ;;;###autoload | 702 ;;;###autoload |
702 (defmacro block (name &rest body) | 703 (defmacro block (name &rest body) |
703 "(block NAME BODY...): define a lexically-scoped block named NAME. | 704 "Define a lexically-scoped block named NAME. |
704 NAME may be any symbol. Code inside the BODY forms can call `return-from' | 705 NAME may be any symbol. Code inside the BODY forms can call `return-from' |
705 to jump prematurely out of the block. This differs from `catch' and `throw' | 706 to jump prematurely out of the block. This differs from `catch' and `throw' |
706 in two respects: First, the NAME is an unevaluated symbol rather than a | 707 in two respects: First, the NAME is an unevaluated symbol rather than a |
707 quoted symbol or other form; and second, NAME is lexically rather than | 708 quoted symbol or other form; and second, NAME is lexically rather than |
708 dynamically scoped: Only references to it within BODY will work. These | 709 dynamically scoped: Only references to it within BODY will work. These |
713 (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) | 714 (list* 'catch (list 'quote (intern (format "--cl-block-%s--" name))) |
714 body)))) | 715 body)))) |
715 | 716 |
716 (defvar cl-active-block-names nil) | 717 (defvar cl-active-block-names nil) |
717 | 718 |
718 (put 'cl-block-wrapper 'byte-compile 'cl-byte-compile-block) | 719 (put 'cl-block-wrapper 'byte-compile |
719 (defun cl-byte-compile-block (cl-form) | 720 #'(lambda (cl-form) |
720 (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing compiler | 721 (if (/= (length cl-form) 2) |
721 (progn | 722 (byte-compile-warn-wrong-args cl-form 1)) |
722 (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) | 723 |
723 (cl-active-block-names (cons cl-entry cl-active-block-names)) | 724 (if (fboundp 'byte-compile-form-do-effect) ; Check for optimizing |
724 (cl-body (byte-compile-top-level | 725 ; compiler |
725 (cons 'progn (cddr (nth 1 cl-form)))))) | 726 (progn |
726 (if (cdr cl-entry) | 727 (let* ((cl-entry (cons (nth 1 (nth 1 (nth 1 cl-form))) nil)) |
727 (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) cl-body)) | 728 (cl-active-block-names (cons cl-entry |
728 (byte-compile-form cl-body)))) | 729 cl-active-block-names)) |
729 (byte-compile-form (nth 1 cl-form)))) | 730 (cl-body (byte-compile-top-level |
730 | 731 (cons 'progn (cddr (nth 1 cl-form)))))) |
731 (put 'cl-block-throw 'byte-compile 'cl-byte-compile-throw) | 732 (if (cdr cl-entry) |
732 (defun cl-byte-compile-throw (cl-form) | 733 (byte-compile-form (list 'catch (nth 1 (nth 1 cl-form)) |
733 (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) | 734 cl-body)) |
734 (if cl-found (setcdr cl-found t))) | 735 (byte-compile-form cl-body)))) |
735 (byte-compile-normal-call (cons 'throw (cdr cl-form)))) | 736 (byte-compile-form (nth 1 cl-form))))) |
737 | |
738 (put 'cl-block-throw 'byte-compile | |
739 #'(lambda (cl-form) | |
740 (let ((cl-found (assq (nth 1 (nth 1 cl-form)) cl-active-block-names))) | |
741 (if cl-found (setcdr cl-found t))) | |
742 (byte-compile-throw (cons 'throw (cdr cl-form))))) | |
736 | 743 |
737 ;;;###autoload | 744 ;;;###autoload |
738 (defmacro return (&optional result) | 745 (defmacro return (&optional result) |
739 "(return [RESULT]): return from the block named nil. | 746 "Return from the block named nil. |
740 This is equivalent to `(return-from nil RESULT)'." | 747 This is equivalent to `(return-from nil RESULT)'." |
741 (list 'return-from nil result)) | 748 (list 'return-from nil result)) |
742 | 749 |
743 ;;;###autoload | 750 ;;;###autoload |
744 (defmacro return-from (name &optional result) | 751 (defmacro return-from (name &optional result) |
745 "(return-from NAME [RESULT]): return from the block named NAME. | 752 "Return from the block named NAME. |
746 This jumps out to the innermost enclosing `(block NAME ...)' form, | 753 This jumps out to the innermost enclosing `(block NAME ...)' form, |
747 returning RESULT from that form (or nil if RESULT is omitted). | 754 returning RESULT from that form (or nil if RESULT is omitted). |
748 This is compatible with Common Lisp, but note that `defun' and | 755 This is compatible with Common Lisp, but note that `defun' and |
749 `defmacro' do not create implicit blocks as they do in Common Lisp." | 756 `defmacro' do not create implicit blocks as they do in Common Lisp." |
750 (let ((name2 (intern (format "--cl-block-%s--" name)))) | 757 (let ((name2 (intern (format "--cl-block-%s--" name)))) |
1695 | 1702 |
1696 ;;; Binding control structures. | 1703 ;;; Binding control structures. |
1697 | 1704 |
1698 ;;;###autoload | 1705 ;;;###autoload |
1699 (defmacro progv (symbols values &rest body) | 1706 (defmacro progv (symbols values &rest body) |
1700 "(progv SYMBOLS VALUES BODY...): bind SYMBOLS to VALUES dynamically in BODY. | 1707 "Bind SYMBOLS to VALUES dynamically in BODY. |
1701 The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. | 1708 The forms SYMBOLS and VALUES are evaluated, and must evaluate to lists. |
1702 Each SYMBOL in the first list is bound to the corresponding VALUE in the | 1709 Each SYMBOL in the first list is bound to the corresponding VALUE in the |
1703 second list (or made unbound if VALUES is shorter than SYMBOLS); then the | 1710 second list (or made unbound if VALUES is shorter than SYMBOLS); then the |
1704 BODY forms are executed and their result is returned. This is much like | 1711 BODY forms are executed and their result is returned. This is much like |
1705 a `let' form, except that the list of symbols can be computed at run-time." | 1712 a `let' form, except that the list of symbols can be computed at run-time." |
1784 cl-macro-environment))))) | 1791 cl-macro-environment))))) |
1785 | 1792 |
1786 (defvar cl-closure-vars nil) | 1793 (defvar cl-closure-vars nil) |
1787 ;;;###autoload | 1794 ;;;###autoload |
1788 (defmacro lexical-let (bindings &rest body) | 1795 (defmacro lexical-let (bindings &rest body) |
1789 "(lexical-let BINDINGS BODY...): like `let', but lexically scoped. | 1796 "Like `let', but lexically scoped. |
1790 The main visible difference is that lambdas inside BODY will create | 1797 The main visible difference is that lambdas inside BODY will create |
1791 lexical closures as in Common Lisp." | 1798 lexical closures as in Common Lisp." |
1792 (let* ((cl-closure-vars cl-closure-vars) | 1799 (let* ((cl-closure-vars cl-closure-vars) |
1793 (vars (mapcar #'(lambda (x) | 1800 (vars (mapcar #'(lambda (x) |
1794 (or (consp x) (setq x (list x))) | 1801 (or (consp x) (setq x (list x))) |
1824 vars)) | 1831 vars)) |
1825 ebody)))) | 1832 ebody)))) |
1826 | 1833 |
1827 ;;;###autoload | 1834 ;;;###autoload |
1828 (defmacro lexical-let* (bindings &rest body) | 1835 (defmacro lexical-let* (bindings &rest body) |
1829 "(lexical-let* BINDINGS BODY...): like `let*', but lexically scoped. | 1836 "Like `let*', but lexically scoped. |
1830 The main visible difference is that lambdas inside BODY will create | 1837 The main visible difference is that lambdas inside BODY will create |
1831 lexical closures as in Common Lisp." | 1838 lexical closures as in Common Lisp." |
1832 (if (null bindings) (cons 'progn body) | 1839 (if (null bindings) (cons 'progn body) |
1833 (setq bindings (reverse bindings)) | 1840 (setq bindings (reverse bindings)) |
1834 (while bindings | 1841 (while bindings |
1839 (list 'progn | 1846 (list 'progn |
1840 (list 'defalias (list 'quote func) | 1847 (list 'defalias (list 'quote func) |
1841 (list 'function (cons 'lambda rest))) | 1848 (list 'function (cons 'lambda rest))) |
1842 (list 'quote func))) | 1849 (list 'quote func))) |
1843 | 1850 |
1844 | 1851 ;;; Multiple values. We support full Common Lisp conventions here. |
1845 ;;; Multiple values. | 1852 |
1846 | 1853 ;;;###autoload |
1847 ;;;###autoload | 1854 (defmacro multiple-value-bind (syms form &rest body) |
1848 (defmacro multiple-value-bind (vars form &rest body) | 1855 "Collect and bind multiple return values. |
1849 "(multiple-value-bind (SYM SYM...) FORM BODY): collect multiple return values. | 1856 |
1850 FORM must return a list; the BODY is then executed with the first N elements | 1857 If FORM returns multiple values, each symbol in SYMS is bound to one of |
1851 of this list bound (`let'-style) to each of the symbols SYM in turn. This | 1858 them, in order, and BODY is executed. If FORM returns fewer multiple values |
1852 is analogous to the Common Lisp `multiple-value-bind' macro, using lists to | 1859 than there are SYMS, remaining SYMS are bound to nil. If FORM does |
1853 simulate true multiple return values. For compatibility, (values A B C) is | 1860 not return multiple values, it is treated as returning one multiple value. |
1854 a synonym for (list A B C)." | 1861 |
1855 (let ((temp (gensym)) (n -1)) | 1862 Returns the value given by the last element of BODY." |
1856 (list* 'let* (cons (list temp form) | 1863 (if (null syms) |
1857 (mapcar #'(lambda (v) | 1864 `(progn ,form ,@body) |
1858 (list v (list 'nth (setq n (1+ n)) temp))) | 1865 (if (= 1 (length syms)) |
1859 vars)) | 1866 ;; Code written to deal with other "implementations" of multiple |
1860 body))) | 1867 ;; values may have a one-element SYMS. |
1861 | 1868 `(let ((,(car syms) ,form)) |
1862 ;;;###autoload | 1869 ,@body) |
1863 (defmacro multiple-value-setq (vars form) | 1870 (let ((temp (gensym))) |
1864 "(multiple-value-setq (SYM SYM...) FORM): collect multiple return values. | 1871 `(let* ((,temp (multiple-value-list-internal 0 ,(length syms) ,form)) |
1865 FORM must return a list; the first N elements of this list are stored in | 1872 ,@(loop |
1866 each of the symbols SYM in turn. This is analogous to the Common Lisp | 1873 for var in syms |
1867 `multiple-value-setq' macro, using lists to simulate true multiple return | 1874 collect `(,var (prog1 (car ,temp) |
1868 values. For compatibility, (values A B C) is a synonym for (list A B C)." | 1875 (setq ,temp (cdr ,temp)))))) |
1869 (cond ((null vars) (list 'progn form nil)) | 1876 ,@body))))) |
1870 ((null (cdr vars)) (list 'setq (car vars) (list 'car form))) | 1877 |
1871 (t | 1878 ;;;###autoload |
1872 (let* ((temp (gensym)) (n 0)) | 1879 (defmacro multiple-value-setq (syms form) |
1873 (list 'let (list (list temp form)) | 1880 "Collect and set multiple values. |
1874 (list 'prog1 (list 'setq (pop vars) (list 'car temp)) | 1881 |
1875 (cons 'setq | 1882 FORM should normally return multiple values; the first N values are stored |
1876 (apply 'nconc | 1883 in the symbols in SYMS in turn. If FORM returns fewer than N values, the |
1877 (mapcar | 1884 remaining symbols have their values set to nil. FORM not returning multiple |
1878 #'(lambda (v) | 1885 values is treated as FORM returning one multiple value, with other elements |
1879 (list v (list | 1886 of SYMS initialized to nil. |
1880 'nth | 1887 |
1881 (setq n (1+ n)) | 1888 Returns the first of the multiple values given by FORM." |
1882 temp))) | 1889 (if (null syms) |
1883 vars))))))))) | 1890 ;; Never return multiple values from multiple-value-setq: |
1884 | 1891 (and form `(values ,form)) |
1892 (if (= 1 (length syms)) | |
1893 `(setq ,(car syms) ,form) | |
1894 (let ((temp (gensym))) | |
1895 `(let* ((,temp (multiple-value-list-internal 0 ,(length syms) ,form))) | |
1896 (setq ,@(loop | |
1897 for sym in syms | |
1898 nconc `(,sym (car-safe ,temp) | |
1899 ,temp (cdr-safe ,temp)))) | |
1900 ,(car syms)))))) | |
1901 | |
1902 ;;;###autoload | |
1903 (defmacro multiple-value-list (form) | |
1904 "Evaluate FORM and return a list of the multiple values it returned." | |
1905 `(multiple-value-list-internal 0 multiple-values-limit ,form)) | |
1906 | |
1907 ;;;###autoload | |
1908 (defmacro nth-value (n form) | |
1909 "Evaluate FORM and return the Nth multiple value it returned." | |
1910 (if (integerp n) | |
1911 `(car (multiple-value-list-internal ,n ,(1+ n) ,form)) | |
1912 (let ((temp (gensym))) | |
1913 `(let ((,temp ,n)) | |
1914 (car (multiple-value-list-internal ,temp (1+ ,temp) ,form)))))) | |
1885 | 1915 |
1886 ;;; Declarations. | 1916 ;;; Declarations. |
1887 | 1917 |
1888 ;;;###autoload | 1918 ;;;###autoload |
1889 (defmacro locally (&rest body) (cons 'progn body)) | 1919 (defmacro locally (&rest body) (cons 'progn body)) |
2344 (get-setf-method x cl-macro-environment)) | 2374 (get-setf-method x cl-macro-environment)) |
2345 args)) | 2375 args)) |
2346 (store-temp (gensym "--values-store--"))) | 2376 (store-temp (gensym "--values-store--"))) |
2347 (list (apply 'append (mapcar 'first methods)) | 2377 (list (apply 'append (mapcar 'first methods)) |
2348 (apply 'append (mapcar 'second methods)) | 2378 (apply 'append (mapcar 'second methods)) |
2349 (list store-temp) | 2379 `((,store-temp |
2350 (cons 'list | 2380 (multiple-value-list-internal 0 ,(if args (length args) 1)))) |
2381 (cons 'values | |
2351 (mapcar #'(lambda (m) | 2382 (mapcar #'(lambda (m) |
2352 (cl-setf-do-store (cons (car (third m)) (fourth m)) | 2383 (cl-setf-do-store (cons (car (third m)) (fourth m)) |
2353 (list 'pop store-temp))) | 2384 (list 'pop store-temp))) |
2354 methods)) | 2385 methods)) |
2355 (cons 'list (mapcar 'fifth methods))))) | 2386 (cons 'list (mapcar 'fifth methods))))) |
2408 (sublis subs (nth 4 method))))) | 2439 (sublis subs (nth 4 method))))) |
2409 | 2440 |
2410 (defun cl-setf-do-store (spec val) | 2441 (defun cl-setf-do-store (spec val) |
2411 (let ((sym (car spec)) | 2442 (let ((sym (car spec)) |
2412 (form (cdr spec))) | 2443 (form (cdr spec))) |
2413 (if (or (cl-const-expr-p val) | 2444 (if (consp sym) |
2414 (and (cl-simple-expr-p val) (eq (cl-expr-contains form sym) 1)) | 2445 ;; XEmacs change, only used for implementing #'values at the moment. |
2415 (cl-setf-simple-store-p sym form)) | 2446 (let* ((orig (copy-list sym)) |
2416 (subst val sym form) | 2447 (intermediate (last orig)) |
2417 (list 'let (list (list sym val)) form)))) | 2448 (circular-limit 32)) |
2449 (while (consp (car intermediate)) | |
2450 (when (zerop circular-limit) | |
2451 (error 'circular-list "Form seems to contain loops")) | |
2452 (setq intermediate (last (car intermediate)) | |
2453 circular-limit (1- circular-limit))) | |
2454 (setcdr intermediate (list val)) | |
2455 `(let (,orig) | |
2456 ,form)) | |
2457 (if (or (cl-const-expr-p val) | |
2458 (and (cl-simple-expr-p val) | |
2459 (eq (cl-expr-contains form sym) 1)) | |
2460 (cl-setf-simple-store-p sym form)) | |
2461 (subst val sym form) | |
2462 (list 'let (list (list sym val)) form))))) | |
2418 | 2463 |
2419 (defun cl-setf-simple-store-p (sym form) | 2464 (defun cl-setf-simple-store-p (sym form) |
2420 (and (consp form) (eq (cl-expr-contains form sym) 1) | 2465 (and (consp form) (eq (cl-expr-contains form sym) 1) |
2421 (eq (nth (1- (length form)) form) sym) | 2466 (eq (nth (1- (length form)) form) sym) |
2422 (symbolp (car form)) (fboundp (car form)) | 2467 (symbolp (car form)) (fboundp (car form)) |
2475 (list 'car temp) | 2520 (list 'car temp) |
2476 (cl-setf-do-store (nth 1 method) (list 'cdr temp))))))) | 2521 (cl-setf-do-store (nth 1 method) (list 'cdr temp))))))) |
2477 | 2522 |
2478 ;;;###autoload | 2523 ;;;###autoload |
2479 (defmacro remf (place tag) | 2524 (defmacro remf (place tag) |
2480 "(remf PLACE TAG): remove TAG from property list PLACE. | 2525 "Remove TAG from property list PLACE. |
2481 PLACE may be a symbol, or any generalized variable allowed by `setf'. | 2526 PLACE may be a symbol, or any generalized variable allowed by `setf'. |
2482 The form returns true if TAG was found and removed, nil otherwise." | 2527 The form returns true if TAG was found and removed, nil otherwise." |
2483 (let* ((method (cl-setf-do-modify place t)) | 2528 (let* ((method (cl-setf-do-modify place t)) |
2484 (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--"))) | 2529 (tag-temp (and (not (cl-const-expr-p tag)) (gensym "--remf-tag--"))) |
2485 (val-temp (and (not (cl-simple-expr-p place)) | 2530 (val-temp (and (not (cl-simple-expr-p place)) |
2540 (cl-setf-do-store (nth 1 method) form)))))) | 2585 (cl-setf-do-store (nth 1 method) form)))))) |
2541 (let ((method (cl-setf-do-modify (car places) 'unsafe))) | 2586 (let ((method (cl-setf-do-modify (car places) 'unsafe))) |
2542 (list 'let* (append (car method) (list (list temp (nth 2 method)))) | 2587 (list 'let* (append (car method) (list (list temp (nth 2 method)))) |
2543 (cl-setf-do-store (nth 1 method) form) nil))))) | 2588 (cl-setf-do-store (nth 1 method) form) nil))))) |
2544 | 2589 |
2590 ;; This function is not in Common Lisp, and there are gaps in its structure and | |
2591 ;; implementation that reflect that it was never well-specified. E.g. with | |
2592 ;; setf, the question of whether a PLACE is bound or not and how to make it | |
2593 ;; unbound doesn't arise, but we need some way of specifying that for letf to | |
2594 ;; be sensible for gethash, symbol-value and so on; currently we just hard-code | |
2595 ;; symbol-value, symbol-function and values (the latter is XEmacs work that | |
2596 ;; I've just done) in the body of this function, and the following gives the | |
2597 ;; wrong behaviour for gethash: | |
2598 ;; | |
2599 ;; (setq my-hash-table #s(hash-table test equal data ()) | |
2600 ;; print-gensym t) | |
2601 ;; => t | |
2602 ;; (gethash "my-key" my-hash-table (gensym)) | |
2603 ;; => #:G68010 | |
2604 ;; (letf (((gethash "my-key" my-hash-table) 4000)) | |
2605 ;; (message "key value is %S" (gethash "my-key" my-hash-table))) | |
2606 ;; => "key value is 4000" | |
2607 ;; (gethash "my-key" my-hash-table (gensym)) | |
2608 ;; => nil ;; should be an uninterned symbol. | |
2609 ;; | |
2610 ;; Aidan Kehoe, Fr Nov 13 16:12:21 GMT 2009 | |
2611 | |
2545 ;;;###autoload | 2612 ;;;###autoload |
2546 (defmacro letf (bindings &rest body) | 2613 (defmacro letf (bindings &rest body) |
2547 "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. | 2614 "(letf ((PLACE VALUE) ...) BODY...): temporarily bind to PLACEs. |
2548 This is the analogue of `let', but with generalized variables (in the | 2615 This is the analogue of `let', but with generalized variables (in the |
2549 sense of `setf') for the PLACEs. Each PLACE is set to the corresponding | 2616 sense of `setf') for the PLACEs. Each PLACE is set to the corresponding |
2561 (list 'symbol-value (list 'quote (caar rev))) | 2628 (list 'symbol-value (list 'quote (caar rev))) |
2562 (caar rev))) | 2629 (caar rev))) |
2563 (value (cadar rev)) | 2630 (value (cadar rev)) |
2564 (method (cl-setf-do-modify place 'no-opt)) | 2631 (method (cl-setf-do-modify place 'no-opt)) |
2565 (save (gensym "--letf-save--")) | 2632 (save (gensym "--letf-save--")) |
2566 (bound (and (memq (car place) '(symbol-value symbol-function)) | 2633 (bound (and (memq (car place) |
2634 '(symbol-value symbol-function values)) | |
2567 (gensym "--letf-bound--"))) | 2635 (gensym "--letf-bound--"))) |
2568 (temp (and (not (cl-const-expr-p value)) (cdr bindings) | 2636 (temp (and (not (cl-const-expr-p value)) (cdr bindings) |
2569 (gensym "--letf-val--")))) | 2637 (gensym "--letf-val--"))) |
2638 (syms (and (eq 'values (car place)) | |
2639 (gensym "--letf-syms--"))) | |
2640 (cursor (and syms (gensym "--letf-cursor--")))) | |
2570 (setq lets (nconc (car method) | 2641 (setq lets (nconc (car method) |
2571 (if bound | 2642 (cond |
2572 (list (list bound | 2643 (syms |
2573 (list (if (eq (car place) | 2644 `((,syms ',(loop |
2574 'symbol-value) | 2645 for sym in (cdr place) |
2575 'boundp 'fboundp) | 2646 nconc (if (symbolp sym) (list sym)))) |
2576 (nth 1 (nth 2 method)))) | 2647 (,cursor ,syms) |
2577 (list save (list 'and bound | 2648 (,bound nil) |
2578 (nth 2 method)))) | 2649 (,save |
2579 (list (list save (nth 2 method)))) | 2650 (prog2 |
2651 (while (consp ,cursor) | |
2652 (setq ,bound | |
2653 (cons (and (boundp (car ,cursor)) | |
2654 (symbol-value | |
2655 (car ,cursor))) | |
2656 ,bound) | |
2657 ,cursor (cdr ,cursor))) | |
2658 ;; Just using ,bound as a temporary | |
2659 ;; variable here, to initialise ,save: | |
2660 (nreverse ,bound) | |
2661 ;; Now, really initialise ,bound: | |
2662 (setq ,cursor ,syms | |
2663 ,bound nil | |
2664 ,bound | |
2665 (progn (while (consp ,cursor) | |
2666 (setq ,bound | |
2667 (cons | |
2668 (boundp (car ,cursor)) | |
2669 ,bound) | |
2670 ,cursor (cdr ,cursor))) | |
2671 (nreverse ,bound))))))) | |
2672 (bound | |
2673 (list (list bound | |
2674 (list (if (eq (car place) | |
2675 'symbol-value) | |
2676 'boundp 'fboundp) | |
2677 (nth 1 (nth 2 method)))) | |
2678 (list save (list 'and bound | |
2679 (nth 2 method))))) | |
2680 (t | |
2681 (list (list save (nth 2 method))))) | |
2580 (and temp (list (list temp value))) | 2682 (and temp (list (list temp value))) |
2581 lets) | 2683 lets) |
2582 body (list | 2684 body (list |
2583 (list 'unwind-protect | 2685 (list 'unwind-protect |
2584 (cons 'progn | 2686 (cons 'progn |
2585 (if (cdr (car rev)) | 2687 (if (cdr (car rev)) |
2586 (cons (cl-setf-do-store (nth 1 method) | 2688 (cons (cl-setf-do-store (nth 1 method) |
2587 (or temp value)) | 2689 (or temp value)) |
2588 body) | 2690 body) |
2589 body)) | 2691 body)) |
2590 (if bound | 2692 (cond |
2591 (list 'if bound | 2693 (syms |
2592 (cl-setf-do-store (nth 1 method) save) | 2694 `(while (consp ,syms) |
2593 (list (if (eq (car place) 'symbol-value) | 2695 (if (car ,bound) |
2594 'makunbound 'fmakunbound) | 2696 (set (car ,syms) (car ,save)) |
2595 (nth 1 (nth 2 method)))) | 2697 (makunbound (car ,syms))) |
2596 (cl-setf-do-store (nth 1 method) save)))) | 2698 (setq ,syms (cdr ,syms) |
2699 ,bound (cdr ,bound) | |
2700 ,save (cdr ,save)))) | |
2701 (bound | |
2702 (list 'if bound | |
2703 (cl-setf-do-store (nth 1 method) save) | |
2704 (list (if (eq (car place) | |
2705 'symbol-function) | |
2706 'fmakunbound | |
2707 'makunbound) | |
2708 (nth 1 (nth 2 method))))) | |
2709 (t | |
2710 (cl-setf-do-store (nth 1 method) save))))) | |
2597 rev (cdr rev)))) | 2711 rev (cdr rev)))) |
2598 (list* 'let* lets body)))) | 2712 (list* 'let* lets body)))) |
2599 | 2713 |
2600 ;;;###autoload | 2714 ;;;###autoload |
2601 (defmacro letf* (bindings &rest body) | 2715 (defmacro letf* (bindings &rest body) |
2614 (setq body (list (list* 'letf (list (pop bindings)) body)))) | 2728 (setq body (list (list* 'letf (list (pop bindings)) body)))) |
2615 (car body))) | 2729 (car body))) |
2616 | 2730 |
2617 ;;;###autoload | 2731 ;;;###autoload |
2618 (defmacro callf (func place &rest args) | 2732 (defmacro callf (func place &rest args) |
2619 "(callf FUNC PLACE ARGS...): set PLACE to (FUNC PLACE ARGS...). | 2733 "Set PLACE to (FUNC PLACE ARGS...). |
2620 FUNC should be an unquoted function name. PLACE may be a symbol, | 2734 FUNC should be an unquoted function name. PLACE may be a symbol, |
2621 or any generalized variable allowed by `setf'." | 2735 or any generalized variable allowed by `setf'." |
2622 (let* ((method (cl-setf-do-modify place (cons 'list args))) | 2736 (let* ((method (cl-setf-do-modify place (cons 'list args))) |
2623 (rargs (cons (nth 2 method) args))) | 2737 (rargs (cons (nth 2 method) args))) |
2624 (list 'let* (car method) | 2738 (list 'let* (car method) |
2627 (list* 'funcall (list 'function func) | 2741 (list* 'funcall (list 'function func) |
2628 rargs)))))) | 2742 rargs)))))) |
2629 | 2743 |
2630 ;;;###autoload | 2744 ;;;###autoload |
2631 (defmacro callf2 (func arg1 place &rest args) | 2745 (defmacro callf2 (func arg1 place &rest args) |
2632 "(callf2 FUNC ARG1 PLACE ARGS...): set PLACE to (FUNC ARG1 PLACE ARGS...). | 2746 "Set PLACE to (FUNC ARG1 PLACE ARGS...). |
2633 Like `callf', but PLACE is the second argument of FUNC, not the first." | 2747 Like `callf', but PLACE is the second argument of FUNC, not the first." |
2634 (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func)) | 2748 (if (and (cl-safe-expr-p arg1) (cl-simple-expr-p place) (symbolp func)) |
2635 (list 'setf place (list* func arg1 place args)) | 2749 (list 'setf place (list* func arg1 place args)) |
2636 (let* ((method (cl-setf-do-modify place (cons 'list args))) | 2750 (let* ((method (cl-setf-do-modify place (cons 'list args))) |
2637 (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--"))) | 2751 (temp (and (not (cl-const-expr-p arg1)) (gensym "--arg1--"))) |
2642 (list* 'funcall (list 'function func) | 2756 (list* 'funcall (list 'function func) |
2643 rargs))))))) | 2757 rargs))))))) |
2644 | 2758 |
2645 ;;;###autoload | 2759 ;;;###autoload |
2646 (defmacro define-modify-macro (name arglist func &optional doc) | 2760 (defmacro define-modify-macro (name arglist func &optional doc) |
2647 "(define-modify-macro NAME ARGLIST FUNC): define a `setf'-like modify macro. | 2761 "Define a `setf'-like modify macro. |
2648 If NAME is called, it combines its PLACE argument with the other arguments | 2762 If NAME is called, it combines its PLACE argument with the other arguments |
2649 from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" | 2763 from ARGLIST using FUNC: (define-modify-macro incf (&optional (n 1)) +)" |
2650 (if (memq '&key arglist) (error "&key not allowed in define-modify-macro")) | 2764 (if (memq '&key arglist) (error "&key not allowed in define-modify-macro")) |
2651 (let ((place (gensym "--place--"))) | 2765 (let ((place (gensym "--place--"))) |
2652 (list 'defmacro* name (cons place arglist) doc | 2766 (list 'defmacro* name (cons place arglist) doc |
2896 | 3010 |
2897 ;;; Types and assertions. | 3011 ;;; Types and assertions. |
2898 | 3012 |
2899 ;;;###autoload | 3013 ;;;###autoload |
2900 (defmacro deftype (name arglist &rest body) | 3014 (defmacro deftype (name arglist &rest body) |
2901 "(deftype NAME ARGLIST BODY...): define NAME as a new data type. | 3015 "Define NAME as a new data type. |
2902 The type name can then be used in `typecase', `check-type', etc." | 3016 The type name can then be used in `typecase', `check-type', etc." |
2903 (list 'eval-when '(compile load eval) | 3017 (list 'eval-when '(compile load eval) |
2904 (cl-transform-function-property | 3018 (cl-transform-function-property |
2905 name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) arglist) body)))) | 3019 name 'cl-deftype-handler (cons (list* '&cl-defs ''('*) arglist) body)))) |
2906 | 3020 |
3004 | 3118 |
3005 ;;; Compiler macros. | 3119 ;;; Compiler macros. |
3006 | 3120 |
3007 ;;;###autoload | 3121 ;;;###autoload |
3008 (defmacro define-compiler-macro (func args &rest body) | 3122 (defmacro define-compiler-macro (func args &rest body) |
3009 "(define-compiler-macro FUNC ARGLIST BODY...): Define a compiler-only macro. | 3123 "Define a compiler-only macro. |
3010 This is like `defmacro', but macro expansion occurs only if the call to | 3124 This is like `defmacro', but macro expansion occurs only if the call to |
3011 FUNC is compiled (i.e., not interpreted). Compiler macros should be used | 3125 FUNC is compiled (i.e., not interpreted). Compiler macros should be used |
3012 for optimizing the way calls to FUNC are compiled; the form returned by | 3126 for optimizing the way calls to FUNC are compiled; the form returned by |
3013 BODY should do the same thing as a call to the normal function called | 3127 BODY should do the same thing as a call to the normal function called |
3014 FUNC, though possibly more efficiently. Note that, like regular macros, | 3128 FUNC, though possibly more efficiently. Note that, like regular macros, |
3167 (cl-simple-expr-p val)) res | 3281 (cl-simple-expr-p val)) res |
3168 (let ((temp (gensym))) | 3282 (let ((temp (gensym))) |
3169 (list 'let (list (list temp val)) (subst temp val res))))) | 3283 (list 'let (list (list temp val)) (subst temp val res))))) |
3170 form)) | 3284 form)) |
3171 | 3285 |
3286 ;; XEmacs; inline delete-duplicates if it's called with a literal | |
3287 ;; #'equal or #'eq and no other keywords, we want the speed in | |
3288 ;; font-lock.el. | |
3289 (define-compiler-macro delete-duplicates (&whole form cl-seq &rest cl-keys) | |
3290 (let ((listp-check | |
3291 (if (memq (car-safe cl-seq) | |
3292 ;; No need to check for a list at runtime with these. We | |
3293 ;; could expand the list, but these are all the functions | |
3294 ;; in the relevant context at the moment. | |
3295 '(nreverse append nconc mapcan mapcar)) | |
3296 t | |
3297 '(listp begin)))) | |
3298 (cond ((and (= 4 (length form)) | |
3299 (eq :test (third form)) | |
3300 (or (equal '(quote eq) (fourth form)) | |
3301 (equal '(function eq) (fourth form)))) | |
3302 `(let* ((begin ,cl-seq) | |
3303 (cl-seq begin)) | |
3304 (if ,listp-check | |
3305 (progn | |
3306 (while cl-seq | |
3307 (setq cl-seq (setcdr cl-seq (delq (car cl-seq) | |
3308 (cdr cl-seq))))) | |
3309 begin) | |
3310 ;; Call cl-delete-duplicates explicitly, to avoid the form | |
3311 ;; getting compiler-macroexpanded again: | |
3312 (cl-delete-duplicates begin ',cl-keys nil)))) | |
3313 ((and (= 4 (length form)) | |
3314 (eq :test (third form)) | |
3315 (or (equal '(quote equal) (fourth form)) | |
3316 (equal '(function equal) (fourth form)))) | |
3317 `(let* ((begin ,cl-seq) | |
3318 (cl-seq begin)) | |
3319 (if ,listp-check | |
3320 (progn | |
3321 (while cl-seq | |
3322 (setq cl-seq (setcdr cl-seq (delete (car cl-seq) | |
3323 (cdr cl-seq))))) | |
3324 begin) | |
3325 ;; Call cl-delete-duplicates explicitly, to avoid the form | |
3326 ;; getting compiler-macroexpanded again: | |
3327 (cl-delete-duplicates begin ',cl-keys nil)))) | |
3328 (t | |
3329 form)))) | |
3330 | |
3331 ;; XEmacs change, the GNU mapc doesn't accept the Common Lisp args, so this | |
3332 ;; change isn't helpful. | |
3333 (define-compiler-macro mapc (&whole form cl-func cl-seq &rest cl-rest) | |
3334 (if cl-rest | |
3335 form | |
3336 (cons 'mapc-internal (cdr form)))) | |
3337 | |
3338 (define-compiler-macro mapcar* (&whole form cl-func cl-x &rest cl-rest) | |
3339 (if cl-rest | |
3340 form | |
3341 (cons 'mapcar (cdr form)))) | |
3342 | |
3343 ;; XEmacs; it's perfectly reasonable, and often much clearer to those | |
3344 ;; reading the code, to call regexp-quote on a constant string, which is | |
3345 ;; something we can optimise here easily. | |
3346 (define-compiler-macro regexp-quote (&whole form string) | |
3347 (if (stringp string) | |
3348 (regexp-quote string) | |
3349 form)) | |
3172 | 3350 |
3173 (mapc | 3351 (mapc |
3174 #'(lambda (y) | 3352 #'(lambda (y) |
3175 (put (car y) 'side-effect-free t) | 3353 (put (car y) 'side-effect-free t) |
3176 (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) | 3354 (put (car y) 'byte-compile 'cl-byte-compile-compiler-macro) |