Mercurial > hg > xemacs-beta
changeset 5737:165315eae1ab
Make #'apply-partially more intelligent still when byte-compiled.
lisp/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea@parhasard.net>
* cl-macs.el:
* cl-macs.el (apply-partially):
Be more intelligent about constructing (or not) compiled functions
at runtime or compile time when making these closures.
tests/ChangeLog addition:
2013-06-17 Aidan Kehoe <kehoea@parhasard.net>
* automated/lisp-tests.el:
Test #'apply-partially more extensively, given changes in
cl-macs.el.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Mon, 17 Jun 2013 19:54:02 +0100 |
parents | 3192994c49ca |
children | f6af091ac654 |
files | lisp/ChangeLog lisp/cl-macs.el tests/ChangeLog tests/automated/lisp-tests.el |
diffstat | 4 files changed, 112 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/lisp/ChangeLog Mon Jun 17 10:23:00 2013 -0600 +++ b/lisp/ChangeLog Mon Jun 17 19:54:02 2013 +0100 @@ -1,3 +1,10 @@ +2013-06-17 Aidan Kehoe <kehoea@parhasard.net> + + * cl-macs.el: + * cl-macs.el (apply-partially): + Be more intelligent about constructing (or not) compiled functions + at runtime or compile time when making these closures. + 2013-03-02 Michael Sperber <mike@xemacs.org> * bytecomp.el (byte-compile-if): Port this patch from GNU Emacs:
--- a/lisp/cl-macs.el Mon Jun 17 10:23:00 2013 -0600 +++ b/lisp/cl-macs.el Mon Jun 17 19:54:02 2013 +0100 @@ -3517,28 +3517,87 @@ (define-compiler-macro apply-partially (&whole form &rest args) "Generate a #'make-byte-code call for #'apply-partially, if appropriate." - (if (< (length args) 1) - form - (if (cl-const-exprs-p args) - `#'(lambda (&rest args) (apply ,@args args)) - (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args))) - (compiled (byte-compile-sexp - `#'(lambda (&rest args) (apply ,@placeholders args))))) - (assert (equal (intersection - (mapcar 'quote-maybe (compiled-function-constants - compiled)) - placeholders :test 'equal :stable t) - placeholders) - t "This macro requires that the relative order is the same\ -in the constants vector and in the arguments") + (when (< (length args) 1) + (return-from apply-partially form)) + (let* ((values (cdr args)) (count (length values)) + (placeholders (mapcar #'quote-maybe (mapcar #'gensym values))) + (sublis (pairlis placeholders values)) + restp lambda arglist bindings compiled) + (when (and (eq 'function (car-safe (nth 0 args))) + (eq 'lambda (car-safe (nth 1 (nth 0 args))))) + (setq lambda (nth 1 (nth 0 args)) + arglist (nth 1 lambda)) + (when (> count (function-max-args lambda)) + (byte-compile-warn + "attempt to apply-partially %S with too many arguments" lambda) + (return-from apply-partially form)) + (while (and arglist placeholders) + (cond ((eq (car arglist) '&optional) + (if restp + (error 'syntax-error + "&optional found after &rest in %S" lambda)) + (if (null (cdr arglist)) + (error 'syntax-error "nothing after &optional in %S" + lambda))) + ((eq (car arglist) '&rest) + (if (null (cdr arglist)) + (error 'syntax-error "nothing after &rest in %S" lambda)) + (if (cdr (cdr arglist)) + (error 'syntax-error "multiple vars after &rest in %S" + lambda)) + (setq restp t)) + (restp + (setq bindings (cons (list (car arglist) + (and placeholders + (cons 'list placeholders))) + bindings) + placeholders nil)) + (t + (setq bindings (cons (list (car arglist) (car placeholders)) + bindings) + placeholders (cdr placeholders)))) + (setq arglist (cdr arglist))) + (when (cl-const-exprs-p values) + ;; Values are constant, no need to construct the compiled function + ;; at runtime. + (return-from apply-partially + (byte-compile-lambda + `(lambda ,arglist (let ,(sublis sublis (nreverse bindings) + :test #'equal) + ,@(cddr lambda)))))) + (setq compiled (byte-compile-lambda + `(lambda ,arglist (let ,(nreverse bindings) + ,@(cddr lambda))))) + (return-from apply-partially `(make-byte-code ',(compiled-function-arglist compiled) ,(compiled-function-instructions compiled) - (vector ,@(sublis (pairlis placeholders args) + (vector ,@(sublis sublis (mapcar 'quote-maybe (compiled-function-constants compiled)) :test 'equal)) - ,(compiled-function-stack-depth compiled)))))) + ,(compiled-function-stack-depth compiled)))) + (if (cl-const-exprs-p args) + `#'(lambda (&rest args) (apply ,@args args)) + (let* ((placeholders (mapcar 'quote-maybe (mapcar 'gensym args))) + (compiled (byte-compile-sexp + `#'(lambda (&rest args) + (apply ,@placeholders args))))) + (assert (equal (intersection + (mapcar 'quote-maybe (compiled-function-constants + compiled)) + placeholders :test 'equal :stable t) + placeholders) + t "This macro requires that the relative order is the same\ +in the constants vector and in the arguments") + `(make-byte-code + ',(compiled-function-arglist compiled) + ,(compiled-function-instructions compiled) + (vector ,@(sublis (pairlis placeholders args) + (mapcar 'quote-maybe + (compiled-function-constants compiled)) + :test 'equal)) + ,(compiled-function-stack-depth compiled)))))) (define-compiler-macro delete-dups (list) `(delete-duplicates (the list ,list) :test #'equal :from-end t))
--- a/tests/ChangeLog Mon Jun 17 10:23:00 2013 -0600 +++ b/tests/ChangeLog Mon Jun 17 19:54:02 2013 +0100 @@ -1,3 +1,9 @@ +2013-06-17 Aidan Kehoe <kehoea@parhasard.net> + + * automated/lisp-tests.el: + Test #'apply-partially more extensively, given changes in + cl-macs.el. + 2013-06-17 Jerry James <james@xemacs.org> * automated/lisp-tests.el: Adjust expected failure message due to
--- a/tests/automated/lisp-tests.el Mon Jun 17 10:23:00 2013 -0600 +++ b/tests/automated/lisp-tests.el Mon Jun 17 19:54:02 2013 +0100 @@ -2950,12 +2950,34 @@ (times-four (apply-partially '* four)) (plus-twelve (apply-partially '+ 6 (* 3 2))) (construct-list (apply-partially 'list (incf four) (incf four) - (incf four)))) + (incf four))) + (list-and-multiply + (apply-partially #'(lambda (a b c d &optional e) + (cons (apply #'+ a b c d (if e (list e))) + (list* a b c d e))) + ;; Constant arguments -> function can be + ;; constructed at compile time + 1 2 3)) + (list-and-four + (apply-partially #'(lambda (a b c d &optional e) + (cons (apply #'+ a b c d (if e (list e))) + (list* a b c d e))) + ;; Not constant arguments -> function constructed + ;; at runtime. + 1 2 four))) (Assert (eql (funcall times-four 6) 24)) (Assert (eql (funcall times-four 4 4) 64)) (Assert (eql (funcall plus-twelve (funcall times-four 4) 4 4) 36)) (Check-Error wrong-number-of-arguments (apply-partially)) - (Assert (equal (funcall construct-list) '(5 6 7)))) + (Assert (equal (funcall construct-list) '(5 6 7))) + (Assert (equal (funcall list-and-multiply 5 6) '(17 1 2 3 5 . 6))) + (Assert (equal (funcall list-and-multiply 7) '(13 1 2 3 7))) + (Check-Error wrong-number-of-arguments + (funcall list-and-multiply 7 8 9 10)) + (Assert (equal (funcall list-and-four 5 6) '(21 1 2 7 5 . 6))) + (Assert (equal (funcall list-and-four 7) '(17 1 2 7 7))) + (Check-Error wrong-number-of-arguments + (funcall list-and-four 7 8 9 10))) ;; Test labels and inlining. (labels