aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Colascione2014-04-21 02:34:21 -0700
committerDaniel Colascione2014-04-21 02:34:21 -0700
commit985c035f2d4cf326a816fe463c400be96e358be2 (patch)
tree8db28fe4100f4e5988824dcc956fd6a7088e98ae
parent0c8d94555ce550d87afd6293bf5d17e864c13864 (diff)
downloademacs-985c035f2d4cf326a816fe463c400be96e358be2.tar.gz
emacs-985c035f2d4cf326a816fe463c400be96e358be2.zip
Correctly treat progn contents as toplevel forms when byte compiling
-rw-r--r--lisp/ChangeLog6
-rw-r--r--lisp/emacs-lisp/bytecomp.el67
-rw-r--r--lisp/emacs-lisp/macroexp.el5
-rw-r--r--test/ChangeLog7
-rw-r--r--test/automated/bytecomp-tests.el50
5 files changed, 111 insertions, 24 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index cb91bbcb4d9..3c5dc44010b 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,11 @@
12014-04-21 Daniel Colascione <dancol@dancol.org> 12014-04-21 Daniel Colascione <dancol@dancol.org>
2 2
3 * emacs-lisp/bytecomp.el (byte-compile-recurse-toplevel): New
4 function.
5 (byte-compile-recurse-toplevel,
6 (byte-compile-initial-macro-environment,
7 (byte-compile-toplevel-file-form): Use it.
8
3 * emacs-lisp/cl-macs.el: 9 * emacs-lisp/cl-macs.el:
4 (cl--loop-let): Properly destructure `while' clauses. 10 (cl--loop-let): Properly destructure `while' clauses.
5 11
diff --git a/lisp/emacs-lisp/bytecomp.el b/lisp/emacs-lisp/bytecomp.el
index e5f8a8cc22a..923d2067a49 100644
--- a/lisp/emacs-lisp/bytecomp.el
+++ b/lisp/emacs-lisp/bytecomp.el
@@ -421,31 +421,46 @@ Filled in `cconv-analyse-form' but initialized and consulted here.")
421 421
422(defvar byte-compiler-error-flag) 422(defvar byte-compiler-error-flag)
423 423
424(defun byte-compile-recurse-toplevel (form &optional non-toplevel-case)
425 "Implement `eval-when-compile' and `eval-and-compile'.
426Return the compile-time value of FORM."
427 ;; Macroexpand (not macroexpand-all!) form at toplevel in case it
428 ;; expands into a toplevel-equivalent `progn'. See CLHS section
429 ;; 3.2.3.1, "Processing of Top Level Forms". The semantics are very
430 ;; subtle: see test/automated/bytecomp-tests.el for interesting
431 ;; cases.
432 (setf form (macroexpand form byte-compile-macro-environment))
433 (if (eq (car-safe form) 'progn)
434 (cons 'progn
435 (mapcar (lambda (subform)
436 (byte-compile-recurse-toplevel
437 subform non-toplevel-case))
438 (cdr form)))
439 (funcall non-toplevel-case form)))
440
424(defconst byte-compile-initial-macro-environment 441(defconst byte-compile-initial-macro-environment
425 '( 442 '(
426 ;; (byte-compiler-options . (lambda (&rest forms) 443 ;; (byte-compiler-options . (lambda (&rest forms)
427 ;; (apply 'byte-compiler-options-handler forms))) 444 ;; (apply 'byte-compiler-options-handler forms)))
428 (declare-function . byte-compile-macroexpand-declare-function) 445 (declare-function . byte-compile-macroexpand-declare-function)
429 (eval-when-compile . (lambda (&rest body) 446 (eval-when-compile . (lambda (&rest body)
430 (list 447 (let ((result nil))
431 'quote 448 (byte-compile-recurse-toplevel
432 (byte-compile-eval 449 (cons 'progn body)
433 (byte-compile-top-level 450 (lambda (form)
434 (byte-compile-preprocess (cons 'progn body))))))) 451 (setf result
452 (byte-compile-eval
453 (byte-compile-top-level
454 (byte-compile-preprocess form))))))
455 (list 'quote result))))
435 (eval-and-compile . (lambda (&rest body) 456 (eval-and-compile . (lambda (&rest body)
436 ;; Byte compile before running it. Do it piece by 457 (byte-compile-recurse-toplevel
437 ;; piece, in case further expressions need earlier 458 (cons 'progn body)
438 ;; ones to be evaluated already, as is the case in 459 (lambda (form)
439 ;; eieio.el. 460 (let ((compiled (byte-compile-top-level
440 `(progn 461 (byte-compile-preprocess form))))
441 ,@(mapcar (lambda (exp) 462 (eval compiled)
442 (let ((cexp 463 compiled))))))
443 (byte-compile-top-level
444 (byte-compile-preprocess
445 exp))))
446 (eval cexp)
447 cexp))
448 body)))))
449 "The default macro-environment passed to macroexpand by the compiler. 464 "The default macro-environment passed to macroexpand by the compiler.
450Placing a macro here will cause a macro to have different semantics when 465Placing a macro here will cause a macro to have different semantics when
451expanded by the compiler as when expanded by the interpreter.") 466expanded by the compiler as when expanded by the interpreter.")
@@ -2198,9 +2213,12 @@ list that represents a doc string reference.
2198 (t form))) 2213 (t form)))
2199 2214
2200;; byte-hunk-handlers cannot call this! 2215;; byte-hunk-handlers cannot call this!
2201(defun byte-compile-toplevel-file-form (form) 2216(defun byte-compile-toplevel-file-form (top-level-form)
2202 (let ((byte-compile-current-form nil)) ; close over this for warnings. 2217 (byte-compile-recurse-toplevel
2203 (byte-compile-file-form (byte-compile-preprocess form t)))) 2218 top-level-form
2219 (lambda (form)
2220 (let ((byte-compile-current-form nil)) ; close over this for warnings.
2221 (byte-compile-file-form (byte-compile-preprocess form t))))))
2204 2222
2205;; byte-hunk-handlers can call this. 2223;; byte-hunk-handlers can call this.
2206(defun byte-compile-file-form (form) 2224(defun byte-compile-file-form (form)
@@ -2942,8 +2960,11 @@ for symbols generated by the byte compiler itself."
2942 interactive-only)) 2960 interactive-only))
2943 (t ".")))) 2961 (t "."))))
2944 (if (eq (car-safe (symbol-function (car form))) 'macro) 2962 (if (eq (car-safe (symbol-function (car form))) 'macro)
2945 (byte-compile-log-warning 2963 (progn
2946 (format "Forgot to expand macro %s" (car form)) nil :error)) 2964 (debug)
2965 (byte-compile-log-warning
2966 (format "Forgot to expand macro %s in %S" (car form) form)
2967 nil :error)))
2947 (if (and handler 2968 (if (and handler
2948 ;; Make sure that function exists. 2969 ;; Make sure that function exists.
2949 (and (functionp handler) 2970 (and (functionp handler)
diff --git a/lisp/emacs-lisp/macroexp.el b/lisp/emacs-lisp/macroexp.el
index e3a746fa69e..c2bfc891b72 100644
--- a/lisp/emacs-lisp/macroexp.el
+++ b/lisp/emacs-lisp/macroexp.el
@@ -97,7 +97,10 @@ each clause."
97(defun macroexp--compiler-macro (handler form) 97(defun macroexp--compiler-macro (handler form)
98 (condition-case err 98 (condition-case err
99 (apply handler form (cdr form)) 99 (apply handler form (cdr form))
100 (error (message "Compiler-macro error for %S: %S" (car form) err) 100 (error
101 (message "--------------------------------------------------")
102 (backtrace)
103 (message "Compiler-macro error for %S: %S" (car form) err)
101 form))) 104 form)))
102 105
103(defun macroexp--funcall-if-compiled (_form) 106(defun macroexp--funcall-if-compiled (_form)
diff --git a/test/ChangeLog b/test/ChangeLog
index 942455ad22b..4003a24bc6b 100644
--- a/test/ChangeLog
+++ b/test/ChangeLog
@@ -1,5 +1,12 @@
12014-04-21 Daniel Colascione <dancol@dancol.org> 12014-04-21 Daniel Colascione <dancol@dancol.org>
2 2
3 * automated/bytecomp-tests.el (test-byte-comp-compile-and-load):
4 New function.
5 (test-byte-comp-macro-expansion)
6 (test-byte-comp-macro-expansion-eval-and-compile)
7 (test-byte-comp-macro-expansion-eval-when-compile)
8 (test-byte-comp-macro-expand-lexical-override): New tests.
9
3 * automated/cl-lib.el (cl-loop-destructuring-with): New test. 10 * automated/cl-lib.el (cl-loop-destructuring-with): New test.
4 (cl-the): Fix cl-the test. 11 (cl-the): Fix cl-the test.
5 12
diff --git a/test/automated/bytecomp-tests.el b/test/automated/bytecomp-tests.el
index 0a9a301dd0d..e61c7c3a41d 100644
--- a/test/automated/bytecomp-tests.el
+++ b/test/automated/bytecomp-tests.el
@@ -305,6 +305,56 @@ Subtests signal errors if something goes wrong."
305 'face fail-face))) 305 'face fail-face)))
306 (insert "\n")))) 306 (insert "\n"))))
307 307
308(defun test-byte-comp-compile-and-load (&rest forms)
309 (let ((elfile nil)
310 (elcfile nil))
311 (unwind-protect
312 (progn
313 (setf elfile (make-temp-file "test-bytecomp" nil ".el"))
314 (setf elcfile (make-temp-file "test-bytecomp" nil ".elc"))
315 (with-temp-buffer
316 (dolist (form forms)
317 (print form (current-buffer)))
318 (write-region (point-min) (point-max) elfile))
319 (let ((byte-compile-dest-file elcfile))
320 (byte-compile-file elfile t)))
321 (when elfile (delete-file elfile))
322 (when elcfile (delete-file elcfile)))))
323(put 'test-byte-comp-compile-and-load 'lisp-indent-function 0)
324
325(ert-deftest test-byte-comp-macro-expansion ()
326 (test-byte-comp-compile-and-load
327 '(progn (defmacro abc (arg) 1) (defun def () (abc 2))))
328 (should (equal (funcall 'def) 1)))
329
330(ert-deftest test-byte-comp-macro-expansion-eval-and-compile ()
331 (test-byte-comp-compile-and-load
332 '(eval-and-compile (defmacro abc (arg) -1) (defun def () (abc 2))))
333 (should (equal (funcall 'def) -1)))
334
335(ert-deftest test-byte-comp-macro-expansion-eval-when-compile ()
336 ;; Make sure we interpret eval-when-compile forms properly. CLISP
337 ;; and SBCL interpreter eval-when-compile (well, the CL equivalent)
338 ;; in the same way.
339 (test-byte-comp-compile-and-load
340 '(eval-when-compile
341 (defmacro abc (arg) -10)
342 (defun abc-1 () (abc 2)))
343 '(defmacro abc-2 () (abc-1))
344 '(defun def () (abc-2)))
345 (should (equal (funcall 'def) -10)))
346
347(ert-deftest test-byte-comp-macro-expand-lexical-override ()
348 ;; Intuitively, one might expect the defmacro to override the
349 ;; macrolet since macrolet's is explicitly called out as being
350 ;; equivalent to toplevel, but CLISP and SBCL both evaluate the form
351 ;; this way, so we should too.
352 (test-byte-comp-compile-and-load
353 '(require 'cl-lib)
354 '(cl-macrolet ((m () 4))
355 (defmacro m () 5)
356 (defun def () (m))))
357 (should (equal (funcall 'def) 4)))
308 358
309;; Local Variables: 359;; Local Variables:
310;; no-byte-compile: t 360;; no-byte-compile: t