mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
Normalise setq during macro-expansion
Early normalisation of setq during macroexpand-all allows later stages, cconv, byte-opt and codegen, to be simplified and duplicated checks to be eliminated. * lisp/emacs-lisp/macroexp.el (macroexp--expand-all): Normalise all setq forms to a sequence of (setq VAR EXPR). Emit warnings if necessary. * lisp/emacs-lisp/cconv.el (cconv-convert, cconv-analyze-form): * lisp/emacs-lisp/byte-opt.el (byte-optimize-form-code-walker): * lisp/emacs-lisp/bytecomp.el (byte-compile-setq): Simplify. * test/lisp/emacs-lisp/bytecomp-tests.el: Adapt and add tests. * test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-nonvariable.el; * test/lisp/emacs-lisp/bytecomp-resources/warn-variable-setq-odd.el: New files.
This commit is contained in:
parent
175bc8e5a5
commit
6825e5686a
7 changed files with 100 additions and 74 deletions
|
|
@ -369,6 +369,54 @@ Assumes the caller has bound `macroexpand-all-environment'."
|
|||
(macroexp--all-forms body))
|
||||
(cdr form))
|
||||
form)))
|
||||
(`(setq ,(and var (pred symbolp)
|
||||
(pred (not booleanp)) (pred (not keywordp)))
|
||||
,expr)
|
||||
;; Fast path for the setq common case.
|
||||
(let ((new-expr (macroexp--expand-all expr)))
|
||||
(if (eq new-expr expr)
|
||||
form
|
||||
`(,fn ,var ,new-expr))))
|
||||
(`(setq . ,args)
|
||||
;; Normalise to a sequence of (setq SYM EXPR).
|
||||
;; Malformed code is translated to code that signals an error
|
||||
;; at run time.
|
||||
(let ((nargs (length args)))
|
||||
(if (/= (logand nargs 1) 0)
|
||||
(macroexp-warn-and-return
|
||||
"odd number of arguments in `setq' form"
|
||||
`(signal 'wrong-number-of-arguments '(setq ,nargs))
|
||||
nil 'compile-only fn)
|
||||
(let ((assignments nil))
|
||||
(while (consp (cdr-safe args))
|
||||
(let* ((var (car args))
|
||||
(expr (cadr args))
|
||||
(new-expr (macroexp--expand-all expr))
|
||||
(assignment
|
||||
(if (and (symbolp var)
|
||||
(not (booleanp var)) (not (keywordp var)))
|
||||
`(,fn ,var ,new-expr)
|
||||
(macroexp-warn-and-return
|
||||
(format-message "attempt to set %s `%s'"
|
||||
(if (symbolp var)
|
||||
"constant"
|
||||
"non-variable")
|
||||
var)
|
||||
(cond
|
||||
((keywordp var)
|
||||
;; Accept `(setq :a :a)' for compatibility.
|
||||
`(if (eq ,var ,new-expr)
|
||||
,var
|
||||
(signal 'setting-constant (list ',var))))
|
||||
((symbolp var)
|
||||
`(signal 'setting-constant (list ',var)))
|
||||
(t
|
||||
`(signal 'wrong-type-argument
|
||||
(list 'symbolp ',var))))
|
||||
nil 'compile-only var))))
|
||||
(push assignment assignments))
|
||||
(setq args (cddr args)))
|
||||
(cons 'progn (nreverse assignments))))))
|
||||
(`(,(and fun `(lambda . ,_)) . ,args)
|
||||
;; Embedded lambda in function position.
|
||||
;; If the byte-optimizer is loaded, try to unfold this,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue