summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Monnier <monnier@iro.umontreal.ca>2011-03-30 14:40:00 -0400
committerStefan Monnier <monnier@iro.umontreal.ca>2011-03-30 14:40:00 -0400
commitf488fb6528738131ef41859e1f04125f2e50efce (patch)
treee064dd58457d2242e581544c3d43a0690ae403ab
parentebe0c9b6b02cfb328457156c25387c3e2b7ba961 (diff)
downloademacs-f488fb6528738131ef41859e1f04125f2e50efce.tar.gz
* lisp/subr.el (apply-partially): Use a non-nil static environment.
(--dolist-tail--, --dotimes-limit--): Don't declare dynamically bound. (dolist): Use a more efficient form for lexical-binding. (dotimes): Use a cleaner semantics for lexical-binding. * lisp/emacs-lisp/edebug.el (edebug-eval-top-level-form): Use eval-sexp-add-defvars.
-rw-r--r--lisp/ChangeLog10
-rw-r--r--lisp/emacs-lisp/edebug.el3
-rw-r--r--lisp/subr.el65
-rw-r--r--src/lread.c1
4 files changed, 56 insertions, 23 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index c1e12152f11..b517c48738f 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,13 @@
+2011-03-30 Stefan Monnier <monnier@iro.umontreal.ca>
+
+ * subr.el (apply-partially): Use a non-nil static environment.
+ (--dolist-tail--, --dotimes-limit--): Don't declare dynamically bound.
+ (dolist): Use a more efficient form for lexical-binding.
+ (dotimes): Use a cleaner semantics for lexical-binding.
+
+ * emacs-lisp/edebug.el (edebug-eval-top-level-form):
+ Use eval-sexp-add-defvars.
+
2011-03-30 Juanma Barranquero <lekktu@gmail.com>
* makefile.w32-in (COMPILE_FIRST): Remove pcase.
diff --git a/lisp/emacs-lisp/edebug.el b/lisp/emacs-lisp/edebug.el
index dfc268421e7..8135b5c4f24 100644
--- a/lisp/emacs-lisp/edebug.el
+++ b/lisp/emacs-lisp/edebug.el
@@ -566,7 +566,8 @@ already is one.)"
;; but this causes problems while edebugging edebug.
(let ((edebug-all-forms t)
(edebug-all-defs t))
- (edebug-read-top-level-form))))
+ (eval-sexp-add-defvars
+ (edebug-read-top-level-form)))))
(defun edebug-read-top-level-form ()
diff --git a/lisp/subr.el b/lisp/subr.el
index c5fedae2bfc..205828b4169 100644
--- a/lisp/subr.el
+++ b/lisp/subr.el
@@ -124,7 +124,7 @@ ARGS is a list of the first N arguments to pass to FUN.
The result is a new function which does the same as FUN, except that
the first N arguments are fixed at the values with which this function
was called."
- `(closure () (&rest args)
+ `(closure (t) (&rest args)
(apply ',fun ,@(mapcar (lambda (arg) `',arg) args) args)))
(if (null (featurep 'cl))
@@ -174,8 +174,6 @@ value of last one, or nil if there are none.
;; If we reload subr.el after having loaded CL, be careful not to
;; overwrite CL's extended definition of `dolist', `dotimes',
;; `declare', `push' and `pop'.
-(defvar --dolist-tail-- nil
- "Temporary variable used in `dolist' expansion.")
(defmacro dolist (spec &rest body)
"Loop over a list.
@@ -189,19 +187,27 @@ Then evaluate RESULT to get return value, default nil.
;; use dolist.
;; FIXME: This cost disappears in byte-compiled lexical-binding files.
(let ((temp '--dolist-tail--))
- `(let ((,temp ,(nth 1 spec))
- ,(car spec))
- (while ,temp
- ;; FIXME: In lexical-binding code, a `let' inside the loop might
- ;; turn out to be faster than the an outside `let' this `setq'.
- (setq ,(car spec) (car ,temp))
- ,@body
- (setq ,temp (cdr ,temp)))
- ,@(if (cdr (cdr spec))
- `((setq ,(car spec) nil) ,@(cdr (cdr spec)))))))
-
-(defvar --dotimes-limit-- nil
- "Temporary variable used in `dotimes' expansion.")
+ ;; This is not a reliable test, but it does not matter because both
+ ;; semantics are acceptable, tho one is slightly faster with dynamic
+ ;; scoping and the other is slightly faster (and has cleaner semantics)
+ ;; with lexical scoping.
+ (if lexical-binding
+ `(let ((,temp ,(nth 1 spec)))
+ (while ,temp
+ (let ((,(car spec) (car ,temp)))
+ ,@body
+ (setq ,temp (cdr ,temp))))
+ ,@(if (cdr (cdr spec))
+ ;; FIXME: This let often leads to "unused var" warnings.
+ `((let ((,(car spec) nil)) ,@(cdr (cdr spec))))))
+ `(let ((,temp ,(nth 1 spec))
+ ,(car spec))
+ (while ,temp
+ (setq ,(car spec) (car ,temp))
+ ,@body
+ (setq ,temp (cdr ,temp)))
+ ,@(if (cdr (cdr spec))
+ `((setq ,(car spec) nil) ,@(cdr (cdr spec))))))))
(defmacro dotimes (spec &rest body)
"Loop a certain number of times.
@@ -214,15 +220,30 @@ the return value (nil if RESULT is omitted).
;; It would be cleaner to create an uninterned symbol,
;; but that uses a lot more space when many functions in many files
;; use dotimes.
+ ;; FIXME: This cost disappears in byte-compiled lexical-binding files.
(let ((temp '--dotimes-limit--)
(start 0)
(end (nth 1 spec)))
- `(let ((,temp ,end)
- (,(car spec) ,start))
- (while (< ,(car spec) ,temp)
- ,@body
- (setq ,(car spec) (1+ ,(car spec))))
- ,@(cdr (cdr spec)))))
+ ;; This is not a reliable test, but it does not matter because both
+ ;; semantics are acceptable, tho one is slightly faster with dynamic
+ ;; scoping and the other has cleaner semantics.
+ (if lexical-binding
+ (let ((counter '--dotimes-counter--))
+ `(let ((,temp ,end)
+ (,counter ,start))
+ (while (< ,counter ,temp)
+ (let ((,(car spec) ,counter))
+ ,@body)
+ (setq ,counter (1+ ,counter)))
+ ,@(if (cddr spec)
+ ;; FIXME: This let often leads to "unused var" warnings.
+ `((let ((,(car spec) ,counter)) ,@(cddr spec))))))
+ `(let ((,temp ,end)
+ (,(car spec) ,start))
+ (while (< ,(car spec) ,temp)
+ ,@body
+ (setq ,(car spec) (1+ ,(car spec))))
+ ,@(cdr (cdr spec))))))
(defmacro declare (&rest specs)
"Do not evaluate any arguments and return nil.
diff --git a/src/lread.c b/src/lread.c
index 7a8d7cf9a6a..24183532527 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -1889,6 +1889,7 @@ which is the input stream for reading characters.
This function does not move point. */)
(Lisp_Object start, Lisp_Object end, Lisp_Object printflag, Lisp_Object read_function)
{
+ /* FIXME: Do the eval-sexp-add-defvars danse! */
int count = SPECPDL_INDEX ();
Lisp_Object tem, cbuf;