comparison lisp/cl-macs.el @ 5562:855b667dea13

Drop cl-macro-environment in favour of byte-compile-macro-environment. lisp/ChangeLog addition: 2011-09-04 Aidan Kehoe <kehoea@parhasard.net> * bytecomp-runtime.el: * bytecomp-runtime.el (byte-compile-macro-environment): Moved from bytecomp.el. * bytecomp.el: * bytecomp.el (byte-compile-initial-macro-environment): Add implementations for #'load-time-value, #'labels here, now cl-macs respects byte-compile-macro-environment. * bytecomp.el (byte-compile-function-environment): * bytecomp.el (byte-compile-macro-environment): Removed. * bytecomp.el (symbol-value): * bytecomp.el (byte-compile-symbol-value): Removed. * cl-extra.el (cl-macroexpand-all): * cl-macs.el: * cl-macs.el (bind-block): * cl-macs.el (cl-macro-environment): Removed. * cl-macs.el (cl-transform-lambda): * cl-macs.el (load-time-value): * cl-macs.el (block): * cl-macs.el (flet): * cl-macs.el (labels): * cl-macs.el (macrolet): * cl-macs.el (symbol-macrolet): * cl-macs.el (lexical-let): * cl-macs.el (apply): * cl-macs.el (nthcdr): * cl-macs.el (getf): * cl-macs.el (substring): * cl-macs.el (values): * cl-macs.el (get-setf-method): * cl-macs.el (cl-setf-do-modify): * cl.el: * cl.el (cl-macro-environment): Removed. * cl.el (cl-macroexpand): * obsolete.el (cl-macro-environment): Moved here. Drop cl-macro-environment, in favour of byte-compile-macro-environment; make the latter available in bytecomp-runtime.el. This makes byte-compile-macro-environment far less useless, since previously code that used cl-macs would ignore it when calling #'cl-macroexpand-all. Add byte-compiler-specific implementations for #'load-time-value, #'labels. The latter is very nice indeed; it avoids the run-time consing of the current implementation, is fully lexical and avoids the run-time shadowing of symbol function slots that flet uses. It would now be reasonable to move most core uses of flet to use labels instead. Non-core code can't rely on print-circle for mutually recursive functions, though, so it's less of an evident win.
author Aidan Kehoe <kehoea@parhasard.net>
date Sun, 04 Sep 2011 20:37:55 +0100
parents 9a93bc90b3bd
children 4654c01af32b
comparison
equal deleted inserted replaced
5561:9a93bc90b3bd 5562:855b667dea13
295 `(put ',func ',prop #'(lambda ,@(cdr (cl-transform-lambda form func))))) 295 `(put ',func ',prop #'(lambda ,@(cdr (cl-transform-lambda form func)))))
296 296
297 (defconst lambda-list-keywords 297 (defconst lambda-list-keywords
298 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment)) 298 '(&optional &rest &key &allow-other-keys &aux &whole &body &environment))
299 299
300 (defvar cl-macro-environment nil)
301 (defvar bind-block) (defvar bind-defs) (defvar bind-enquote) 300 (defvar bind-block) (defvar bind-defs) (defvar bind-enquote)
302 (defvar bind-lets) (defvar bind-forms) 301 (defvar bind-lets) (defvar bind-forms)
303 302
304 ;; npak@ispras.ru 303 ;; npak@ispras.ru
305 (defun cl-upcase-arg (arg) 304 (defun cl-upcase-arg (arg)
368 (if (setq bind-enquote (memq '&cl-quote args)) 367 (if (setq bind-enquote (memq '&cl-quote args))
369 (setq args (delq '&cl-quote args))) 368 (setq args (delq '&cl-quote args)))
370 (if (memq '&whole args) (error "&whole not currently implemented")) 369 (if (memq '&whole args) (error "&whole not currently implemented"))
371 (let* ((p (memq '&environment args)) (v (cadr p))) 370 (let* ((p (memq '&environment args)) (v (cadr p)))
372 (if p (setq args (nconc (delq (car p) (delq v args)) 371 (if p (setq args (nconc (delq (car p) (delq v args))
373 (list '&aux (list v 'cl-macro-environment)))))) 372 `(&aux (,v byte-compile-macro-environment))))))
374 (while (and args (symbolp (car args)) 373 (while (and args (symbolp (car args))
375 (not (memq (car args) '(nil &rest &body &key &aux))) 374 (not (memq (car args) '(nil &rest &body &key &aux)))
376 (not (and (eq (car args) '&optional) 375 (not (and (eq (car args) '&optional)
377 (or bind-defs (consp (cadr args)))))) 376 (or bind-defs (consp (cadr args))))))
378 (push (pop args) simple-args)) 377 (push (pop args) simple-args))
624 623
625 ;;;###autoload 624 ;;;###autoload
626 (defmacro load-time-value (form &optional read-only) 625 (defmacro load-time-value (form &optional read-only)
627 "Like `progn', but evaluates the body at load time. 626 "Like `progn', but evaluates the body at load time.
628 The result of the body appears to the compiler as a quoted constant." 627 The result of the body appears to the compiler as a quoted constant."
629 (let ((gensym (gensym))) 628 (list 'progn form))
630 ;; The body of this macro really should be (cons 'progn form), with the
631 ;; hairier stuff in a shadowed version in
632 ;; byte-compile-initial-macro-environment. That doesn't work because
633 ;; cl-macs.el doesn't respect byte-compile-macro-environment, which is
634 ;; something we should change.
635 (put gensym 'cl-load-time-value-form form)
636 (set gensym (eval form))
637 `(symbol-value ',gensym)))
638 629
639 ;;; Conditional control structures. 630 ;;; Conditional control structures.
640 631
641 ;;;###autoload 632 ;;;###autoload
642 (defmacro case (expr &rest clauses) 633 (defmacro case (expr &rest clauses)
744 (body (cons 'progn body))) 735 (body (cons 'progn body)))
745 ;; Tell the byte-compiler this is a block, not a normal catch call, and 736 ;; Tell the byte-compiler this is a block, not a normal catch call, and
746 ;; as such it can eliminate it if that's appropriate: 737 ;; as such it can eliminate it if that's appropriate:
747 (put (cdar cl-active-block-names) 'cl-block-name name) 738 (put (cdar cl-active-block-names) 'cl-block-name name)
748 `(catch ',(cdar cl-active-block-names) 739 `(catch ',(cdar cl-active-block-names)
749 ,(cl-macroexpand-all body cl-macro-environment)))) 740 ,(cl-macroexpand-all body byte-compile-macro-environment))))
750 741
751 ;;;###autoload 742 ;;;###autoload
752 (defmacro return (&optional result) 743 (defmacro return (&optional result)
753 "Return from the block named nil. 744 "Return from the block named nil.
754 This is equivalent to `(return-from nil RESULT)'." 745 This is equivalent to `(return-from nil RESULT)'."
1736 (list* 'letf* 1727 (list* 'letf*
1737 (mapcar 1728 (mapcar
1738 #'(lambda (x) 1729 #'(lambda (x)
1739 (if (or (and (fboundp (car x)) 1730 (if (or (and (fboundp (car x))
1740 (eq (car-safe (symbol-function (car x))) 'macro)) 1731 (eq (car-safe (symbol-function (car x))) 'macro))
1741 (cdr (assq (car x) cl-macro-environment))) 1732 (cdr (assq (car x) byte-compile-macro-environment)))
1742 (error "Use `labels', not `flet', to rebind macro names")) 1733 (error "Use `labels', not `flet', to rebind macro names"))
1743 (let ((func (list 'function* 1734 (let ((func (list 'function*
1744 (list 'lambda (cadr x) 1735 (list 'lambda (cadr x)
1745 (list* 'block (car x) (cddr x)))))) 1736 (list* 'block (car x) (cddr x))))))
1746 (if (and (cl-compiling-file) 1737 (if (and (cl-compiling-file)
1756 "Make temporary func bindings. 1747 "Make temporary func bindings.
1757 This is like `flet', except the bindings are lexical instead of dynamic. 1748 This is like `flet', except the bindings are lexical instead of dynamic.
1758 Unlike `flet', this macro is fully compliant with the Common Lisp standard. 1749 Unlike `flet', this macro is fully compliant with the Common Lisp standard.
1759 1750
1760 arguments: (((FUNC ARGLIST &body BODY) &rest FUNCTIONS) &body FORM)" 1751 arguments: (((FUNC ARGLIST &body BODY) &rest FUNCTIONS) &body FORM)"
1761 (let ((vars nil) (sets nil) (cl-macro-environment cl-macro-environment)) 1752 (let ((vars nil) (sets nil)
1753 (byte-compile-macro-environment byte-compile-macro-environment))
1762 (while bindings 1754 (while bindings
1763 (let ((var (gensym))) 1755 (let ((var (gensym)))
1764 (push var vars) 1756 (push var vars)
1765 (push (list 'function* (cons 'lambda (cdar bindings))) sets) 1757 (push `#'(lambda ,@(cdr (cl-transform-lambda (cdar bindings)
1758 (caar bindings)))) sets)
1766 (push var sets) 1759 (push var sets)
1767 (push (list (car (pop bindings)) 'lambda '(&rest cl-labels-args) 1760 (push (list (car (pop bindings)) 'lambda '(&rest cl-labels-args)
1768 (list 'list* '(quote funcall) (list 'quote var) 1761 (list 'list* '(quote funcall) (list 'quote var)
1769 'cl-labels-args)) 1762 'cl-labels-args))
1770 cl-macro-environment))) 1763 byte-compile-macro-environment)))
1771 (cl-macroexpand-all (list* 'lexical-let vars (cons (cons 'setq sets) body)) 1764 (cl-macroexpand-all (list* 'lexical-let vars (cons (cons 'setq sets) body))
1772 cl-macro-environment))) 1765 byte-compile-macro-environment)))
1773 1766
1774 ;; The following ought to have a better definition for use with newer 1767 ;; The following ought to have a better definition for use with newer
1775 ;; byte compilers. 1768 ;; byte compilers.
1776 ;;;###autoload 1769 ;;;###autoload
1777 (defmacro* macrolet ((&rest macros) &body form) 1770 (defmacro* macrolet ((&rest macros) &body form)
1783 for (name . details) 1776 for (name . details)
1784 in macros 1777 in macros
1785 collect 1778 collect
1786 (list* name 'lambda (cdr (cl-transform-lambda details 1779 (list* name 'lambda (cdr (cl-transform-lambda details
1787 name)))) 1780 name))))
1788 cl-macro-environment))) 1781 byte-compile-macro-environment)))
1789 1782
1790 ;;;###autoload 1783 ;;;###autoload
1791 (defmacro* symbol-macrolet ((&rest symbol-macros) &body form) 1784 (defmacro* symbol-macrolet ((&rest symbol-macros) &body form)
1792 "Make temporary symbol macro definitions. 1785 "Make temporary symbol macro definitions.
1793 Elements in SYMBOL-MACROS look like (NAME EXPANSION). 1786 Elements in SYMBOL-MACROS look like (NAME EXPANSION).
1796 (cl-macroexpand-all (cons 'progn form) 1789 (cl-macroexpand-all (cons 'progn form)
1797 (nconc (loop 1790 (nconc (loop
1798 for (name expansion) in symbol-macros 1791 for (name expansion) in symbol-macros
1799 do (check-type name symbol) 1792 do (check-type name symbol)
1800 collect (list (eq-hash name) expansion)) 1793 collect (list (eq-hash name) expansion))
1801 cl-macro-environment))) 1794 byte-compile-macro-environment)))
1802 1795
1803 (defvar cl-closure-vars nil) 1796 (defvar cl-closure-vars nil)
1804 ;;;###autoload 1797 ;;;###autoload
1805 (defmacro lexical-let (bindings &rest body) 1798 (defmacro lexical-let (bindings &rest body)
1806 "Like `let', but lexically scoped. 1799 "Like `let', but lexically scoped.
1822 (list (eq-hash (car x)) 1815 (list (eq-hash (car x))
1823 (list 'symbol-value (caddr x)) 1816 (list 'symbol-value (caddr x))
1824 t)) 1817 t))
1825 vars) 1818 vars)
1826 (list '(defun . cl-defun-expander)) 1819 (list '(defun . cl-defun-expander))
1827 cl-macro-environment)))) 1820 byte-compile-macro-environment))))
1828 (if (not (get (car (last cl-closure-vars)) 'used)) 1821 (if (not (get (car (last cl-closure-vars)) 'used))
1829 (list 'let (mapcar #'(lambda (x) (list (caddr x) (cadr x))) vars) 1822 (list 'let (mapcar #'(lambda (x) (list (caddr x) (cadr x))) vars)
1830 (sublis (mapcar #'(lambda (x) 1823 (sublis (mapcar #'(lambda (x)
1831 (cons (caddr x) (list 'quote (caddr x)))) 1824 (cons (caddr x) (list 'quote (caddr x))))
1832 vars) 1825 vars)
2334 (defsetf get-selection own-selection t) 2327 (defsetf get-selection own-selection t)
2335 2328
2336 ;;; More complex setf-methods. 2329 ;;; More complex setf-methods.
2337 ;;; These should take &environment arguments, but since full arglists aren't 2330 ;;; These should take &environment arguments, but since full arglists aren't
2338 ;;; available while compiling cl-macs, we fake it by referring to the global 2331 ;;; available while compiling cl-macs, we fake it by referring to the global
2339 ;;; variable cl-macro-environment directly. 2332 ;;; variable byte-compile-macro-environment directly.
2340 2333
2341 (define-setf-method apply (func arg1 &rest rest) 2334 (define-setf-method apply (func arg1 &rest rest)
2342 (or (and (memq (car-safe func) '(quote function function*)) 2335 (or (and (memq (car-safe func) '(quote function function*))
2343 (symbolp (car-safe (cdr-safe func)))) 2336 (symbolp (car-safe (cdr-safe func))))
2344 (error "First arg to apply in setf is not (function SYM): %s" func)) 2337 (error "First arg to apply in setf is not (function SYM): %s" func))
2345 (let* ((form (cons (nth 1 func) (cons arg1 rest))) 2338 (let* ((form (cons (nth 1 func) (cons arg1 rest)))
2346 (method (get-setf-method form cl-macro-environment))) 2339 (method (get-setf-method form byte-compile-macro-environment)))
2347 (list (car method) (nth 1 method) (nth 2 method) 2340 (list (car method) (nth 1 method) (nth 2 method)
2348 (cl-setf-make-apply (nth 3 method) (cadr func) (car method)) 2341 (cl-setf-make-apply (nth 3 method) (cadr func) (car method))
2349 (cl-setf-make-apply (nth 4 method) (cadr func) (car method))))) 2342 (cl-setf-make-apply (nth 4 method) (cadr func) (car method)))))
2350 2343
2351 (defun cl-setf-make-apply (form func temps) 2344 (defun cl-setf-make-apply (form func temps)
2354 (or (equal (last form) (last temps)) 2347 (or (equal (last form) (last temps))
2355 (error "%s is not suitable for use with setf-of-apply" func)) 2348 (error "%s is not suitable for use with setf-of-apply" func))
2356 (list* 'apply (list 'quote (car form)) (cdr form)))) 2349 (list* 'apply (list 'quote (car form)) (cdr form))))
2357 2350
2358 (define-setf-method nthcdr (n place) 2351 (define-setf-method nthcdr (n place)
2359 (let ((method (get-setf-method place cl-macro-environment)) 2352 (let ((method (get-setf-method place byte-compile-macro-environment))
2360 (n-temp (gensym "--nthcdr-n--")) 2353 (n-temp (gensym "--nthcdr-n--"))
2361 (store-temp (gensym "--nthcdr-store--"))) 2354 (store-temp (gensym "--nthcdr-store--")))
2362 (list (cons n-temp (car method)) 2355 (list (cons n-temp (car method))
2363 (cons n (nth 1 method)) 2356 (cons n (nth 1 method))
2364 (list store-temp) 2357 (list store-temp)
2367 store-temp))) 2360 store-temp)))
2368 (nth 3 method) store-temp) 2361 (nth 3 method) store-temp)
2369 (list 'nthcdr n-temp (nth 4 method))))) 2362 (list 'nthcdr n-temp (nth 4 method)))))
2370 2363
2371 (define-setf-method getf (place tag &optional def) 2364 (define-setf-method getf (place tag &optional def)
2372 (let ((method (get-setf-method place cl-macro-environment)) 2365 (let ((method (get-setf-method place byte-compile-macro-environment))
2373 (tag-temp (gensym "--getf-tag--")) 2366 (tag-temp (gensym "--getf-tag--"))
2374 (def-temp (gensym "--getf-def--")) 2367 (def-temp (gensym "--getf-def--"))
2375 (store-temp (gensym "--getf-store--"))) 2368 (store-temp (gensym "--getf-store--")))
2376 (list (append (car method) (list tag-temp def-temp)) 2369 (list (append (car method) (list tag-temp def-temp))
2377 (append (nth 1 method) (list tag def)) 2370 (append (nth 1 method) (list tag def))
2381 tag-temp store-temp))) 2374 tag-temp store-temp)))
2382 (nth 3 method) store-temp) 2375 (nth 3 method) store-temp)
2383 (list 'getf (nth 4 method) tag-temp def-temp)))) 2376 (list 'getf (nth 4 method) tag-temp def-temp))))
2384 2377
2385 (define-setf-method substring (place from &optional to) 2378 (define-setf-method substring (place from &optional to)
2386 (let ((method (get-setf-method place cl-macro-environment)) 2379 (let ((method (get-setf-method place byte-compile-macro-environment))
2387 (from-temp (gensym "--substring-from--")) 2380 (from-temp (gensym "--substring-from--"))
2388 (to-temp (gensym "--substring-to--")) 2381 (to-temp (gensym "--substring-to--"))
2389 (store-temp (gensym "--substring-store--"))) 2382 (store-temp (gensym "--substring-store--")))
2390 (list (append (car method) (list from-temp to-temp)) 2383 (list (append (car method) (list from-temp to-temp))
2391 (append (nth 1 method) (list from to)) 2384 (append (nth 1 method) (list from to))
2397 (list 'substring (nth 4 method) from-temp to-temp)))) 2390 (list 'substring (nth 4 method) from-temp to-temp))))
2398 2391
2399 ;; XEmacs addition 2392 ;; XEmacs addition
2400 (define-setf-method values (&rest args) 2393 (define-setf-method values (&rest args)
2401 (let ((methods (mapcar #'(lambda (x) 2394 (let ((methods (mapcar #'(lambda (x)
2402 (get-setf-method x cl-macro-environment)) 2395 (get-setf-method x byte-compile-macro-environment))
2403 args)) 2396 args))
2404 (store-temp (gensym "--values-store--"))) 2397 (store-temp (gensym "--values-store--")))
2405 (list (apply 'append (mapcar 'first methods)) 2398 (list (apply 'append (mapcar 'first methods))
2406 (apply 'append (mapcar 'second methods)) 2399 (apply 'append (mapcar 'second methods))
2407 `((,store-temp 2400 `((,store-temp
2426 (let* ((func (car place)) 2419 (let* ((func (car place))
2427 (name (symbol-name func)) 2420 (name (symbol-name func))
2428 (method (get func 'setf-method)) 2421 (method (get func 'setf-method))
2429 (case-fold-search nil)) 2422 (case-fold-search nil))
2430 (or (and method 2423 (or (and method
2431 (let ((cl-macro-environment env)) 2424 (let ((byte-compile-macro-environment env))
2432 (setq method (apply method (cdr place)))) 2425 (setq method (apply method (cdr place))))
2433 (if (and (consp method) (eql (length method) 5)) 2426 (if (and (consp method) (eql (length method) 5))
2434 method 2427 method
2435 (error "Setf-method for %s returns malformed method" 2428 (error "Setf-method for %s returns malformed method"
2436 func))) 2429 func)))
2447 (cdr place)) env) 2440 (cdr place)) env)
2448 (error "No setf-method known for %s" (car place))) 2441 (error "No setf-method known for %s" (car place)))
2449 (get-setf-method place env))))) 2442 (get-setf-method place env)))))
2450 2443
2451 (defun cl-setf-do-modify (place opt-expr) 2444 (defun cl-setf-do-modify (place opt-expr)
2452 (let* ((method (get-setf-method place cl-macro-environment)) 2445 (let* ((method (get-setf-method place byte-compile-macro-environment))
2453 (temps (car method)) (values (nth 1 method)) 2446 (temps (car method)) (values (nth 1 method))
2454 (lets nil) (subs nil) 2447 (lets nil) (subs nil)
2455 (optimize (and (not (eq opt-expr 'no-opt)) 2448 (optimize (and (not (eq opt-expr 'no-opt))
2456 (or (and (not (eq opt-expr 'unsafe)) 2449 (or (and (not (eq opt-expr 'unsafe))
2457 (cl-safe-expr-p opt-expr)) 2450 (cl-safe-expr-p opt-expr))