* lisp/emacs-lisp/pcase.el (pcase-lambda): Copy notice from
'pcase-let', indicating that pcase-lambda won't pattern match
like 'pcase', but just try to destruct with uncertain side
effects if this fails. (Bug#71503)
* lisp/emacs-lisp/pcase.el (pcase--app-subst-match): Optimize matches
against (quote VAL).
* test/lisp/emacs-lisp/pcase-tests.el (pcase-tests-quote-optimization):
Add new test case.
Large backquote patterns tend to lead to very large and deeply
nested expansions, but they also tend to contain a lot of
"constant" subpatterns that can be compiled to quote patterns.
This patch does just that. See discussion at
https://lists.gnu.org/archive/html/emacs-devel/2024-05/msg01140.html
* lisp/emacs-lisp/pcase.el (pcase--split-pred):
Improve the handling of pred-vs-quote so it also works with
quoted objects like cons cells, vectors, and strings.
Simplify the `pcase--mutually-exclusive-p` branch accordingly.
(pcase--expand-\`): New function, extracted from the \` pcase macro.
Make it recurse internally, and optimize backquote patterns to `quote`
patterns where possible.
(\`): Use it.
* test/lisp/emacs-lisp/pcase-tests.el (pcase-tests-vectors): Add tests
that were broken by a more naïve version of the optimization.
(pcase-tests-quote-optimization): New test.
`rm lisp/emacs-lisp/cl-preloaded.elc src/bootstrap-emacs`
followed by `make` ended up loading right after defining
`built-in-class-p` but before actually defining the
built-in-classes so the computation of bitsets failed.
The `pcase-mutually-exclusive-predicates` table was not very
efficient since it grew like O(N²) with the number of
predicates. Replace it with an O(N) table that's auto-generated
from the `built-in-class` objects.
* lisp/emacs-lisp/pcase.el (pcase-mutually-exclusive-predicates):
Delete variable.
(pcase--subtype-bitsets): New function and constant.
(pcase--mutually-exclusive-p): Use them.
* lisp/emacs-lisp/cl-preloaded.el (built-in-class): Don't inline.
The current syntax for functions in `app` and `pred` patterns
allows a shorthand (F ARGS) where the object being matched is
added as an extra last argument. This is nice for things like
(pred (< 5)) but sometimes the object needs to be at
another position.
Until now you had to use (pred (lambda (x) (memq x my-list)))
or (pred (pcase--flip memq my-list)) in those cases.
So, introduce a new shorthand where `_` can be used to indicate
where the object should be passed: (pred (memq _ my-list))
* lisp/emacs-lisp/pcase.el (pcase--split-pred): Document new syntax
for pred/app functions.
(pcase--funcall): Support new syntax.
(pcase--flip): Declare obsolete.
(pcase--u1, \`): Use `_` instead.
(pcase--split-pred): Adjust accordingly.
* doc/lispref/control.texi (pcase Macro): Document new syntax
for pred/app functions.
* lisp/progmodes/opascal.el (pcase-defmacro):
* lisp/emacs-lisp/seq.el (seq--make-pcase-bindings):
* lisp/emacs-lisp/eieio.el (eieio):
* lisp/emacs-lisp/cl-macs.el (cl-struct, cl-type):
Use _ instead of `pcase--flip`.
(cl--pcase-mutually-exclusive-p): Adjust accordingly.
* lisp/emacs-lisp/map.el (map--pcase-map-elt): Declare obsolete.
(map--make-pcase-bindings): Use `_` instead.
* lisp/emacs-lisp/pcase.el (pcase--find-macro-def-regexp): New var.
(find-function-regexp-alist): Add entry for `pcase-macro`s.
(help-fns--signature): Move declaration to where we know it is valid.
(pcase--make-docstring): Add buttons to jump to the definition
of Pcase macros.
The position return by read-positioning-symbols is now the position in the
buffer, rather than the offset from the start of a form, enabling warning
positions in other parts of the buffer to be output.
* src/lisp.h (lisp_h_EQ): Add XLI casts so that it compiles cleanly.
* src/data.c (Fremove_pos_from_symbol): New DEFUN.
* src/lread.c (readchar_count): renamed to readchar_offset.
(read_internal_start) Initialize readchar_offset to the buffer's point when
STREAM is a buffer.
* lisp/emacs-lisp/bytecomp.el (byte-compile-warning-prefix): Amend to use
OFFSET as a buffer position, not an offset from the start of a form.
(byte-compile-warn): Remove symbol positions from any shape of ARGS, not just
a symbol with position.
* lisp/emacs-lisp/cconv.c (cconv-convert): In the :unused case, position the
new IGNORE symbol with the VAR it has replaced.
* lisp/emacs-lisp/macroexp.el (macroexp--warn-wrap, macroexp-warn-and-return):
Add an extra position parameter to each.
* lisp/emacs-lisp/bindat.el (bindat-type), lisp/emacs-lisp/byte-run.el
(defmacro, defun), lisp/emacs-lisp/cconv.el (cconv--convert-func-body)
(cconv-convert), lisp/emacs-lisp/cl-generic.el (cl-defmethod),
lisp/emacs-lisp/cl-macs.el (cl-symbol-macrolet, cl-defstruct),
lisp/emacs-lisp/easy-mmode.el (define-minor-mode),
lisp/emacs-lisp/eieio-core.el (eieio-oref, eieio-oref-default)
(eieio-oset-default), lisp/emacs-lisp/eieio.el (defclass),
lisp/emacs-lisp/gv.el (gv-ref), lisp/emacs-lisp/macroexp.el
(macroexp-macroexpand, macroexp--unfold-lambda, macroexp--expand-all),
lisp/emacs-lisp/pcase.el (pcase-compile-patterns, pcase--u1): Add an extra
position argument to each call of macroexp-warn-and-return.
This branch is intended to generate correct position information in warning
and error messages from the byte compiler, and is intended thereby to fix bugs
It introduces a new mechanism, the symbol with position. This is taken over
from the previous git branch scratch/accurate-warning-pos which was abandoned
for being too slow. The main difference in the current branch is that the
symbol `nil' is never given a position, thus speeding up NILP markedly.
* lisp/emacs-lisp/byte-opt.el (byte-compile-inline-expand)
(byte-optimize-form-code-walker, byte-optimize-let-form, byte-optimize-while)
(byte-optimize-apply): Use byte-compile-warn-x in place of byte-compile-warn.
* lisp/emacs-lisp/bytecomp.el (byte-compile--form-stack): New variable.
(byte-compile-strip-s-p-1, byte-compile-strip-symbol-positions): New
functions.
(byte-compile-recurse-toplevel, byte-compile-initial-macro-environment)
(byte-compile-preprocess, byte-compile-macroexpand-declare-function): Bind
print-symbols-bare to non-nil.
(byte-compile--first-symbol, byte-compile--warning-source-offset): New
functions.
(byte-compile-warning-prefix): Modify to output two sets of position
information, the old (incorrect) set and the new set.
(byte-compile-warn): Strip positions from symbols before outputting.
(byte-compile-warn-x): New function which outputs a correct position supplied
in an argument.
(byte-compile-warn-obsolete, byte-compile-emit-callargs-warn)
(byte-compile-format-warn, byte-compile-nogroup-warn)
(byte-compile-arglist-warn, byte-compile-docstring-length-warn)
(byte-compile-warn-about-unresolved-functions, byte-compile-file)
(byte-compile--check-prefixed-var, byte-compile--declare-var)
(byte-compile-file-form-defvar-function, byte-compile-file-form-defmumble)
(byte-compile-check-lambda-list, byte-compile--warn-lexical-dynamic)
(byte-compile-lambda, byte-compile-form, byte-compile-normal-call)
(byte-compile-check-variable, byte-compile-free-vars-warn)
(byte-compile-subr-wrong-args, byte-compile-fset, byte-compile-set-default)
(byte-compile-condition-case, byte-compile-save-excursion)
(byte-compile-defvar, byte-compile-autoload)
(byte-compile-make-variable-buffer-local, byte-compile-define-symbol-prop)
(byte-compile-define-keymap): Replace byte-compile-warn with
byte-compile-warn-x.
(byte-compile-file, compile-defun): Bind symbols-with-pos-enabled to non-nil.
(compile-defun, byte-compile-from-buffer): Use `read-positioning-symbols'
rather than plain `read'.
(byte-compile-toplevel-file-form, byte-compile-form): Dynamically bind
byte-compile--form-stack.
(byte-compile-file-form-autoload, byte-compile-file-form-defvar)
(byte-compile-file-form-make-obsolete, byte-compile-lambda)
(byte-compile-push-constant, byte-compile-cond-jump-table)
(byte-compile-define-keymap, byte-compile-annotate-call-tree):
Strip positions from symbols where they are unwanted.
(byte-compile-file-form-defvar): Strip positions from symbols using
`bare-symbol'.
(byte-compile-file-form-defmumble): New variable bare-name, a version of name
without its position.
(byte-compile-lambda): Similarly, new variable bare-arglist.
(byte-compile-free-vars-warn): New argument arg supplying position information
to byte-compile-warn-x.
(byte-compile-push-constant): Manipulation of symbol positions.
(display-call-tree): Strip positions from symbols.
* lisp/emacs-lisp/cconv.el (cconv-convert, cconv--analyze-use)
(cconv--analyze-function, cconv-analyze-form): Replace use of
byte-compile-warn with byte-compile-warn-x.
* lisp/emacs-lisp/cl-generic.el (cl-defmethod): New variable org-name which
will supply position information to a new macroexp-warn-and-return.
* lisp/emacs-lisp/cl-macs.el (cl-macs--strip-s-p-1)
(cl-macs--strip-symbol-positions): New functions to strip positions from
symbols in an expression. These duplicaate similarly named functions in
bytecomp.el.
* lisp/emacs-lisp/macroexpand.el (macroexp--warn-wrap): Calls
byte-compile-warn-x in place of byte-compile-warn.
(macroexp-warn-and-return): Commented out new position parameter _arg.
* src/.gdbinit: Add in code to handle symbols with position.
* src/alloc.c (XPNTR, set_symbol_name, valid_lisp_object_p, purecopy)
(mark_char_table, mark_object, survives_gc_p, symbol_uses_obj): Use
BARE_SYMBOL_P and XBARE_SYMBOL in place of the former SYMBOLP and XSYMBOL.
(build_symbol_with_pos): New function.
(Fgarbage_collect): Bind Qsymbols_with_pos_enabled to nil around the call to
garbage_collect.
* src/data.c (Ftype_of): Add case for PVEC_SYMBOL_WITH_POS.
(Fbare_symbol_p, Fsymbol_with_pos_p, Fbare_symbol, Fsymbol_with_pos_pos)
(Fposition_symbol): New functions.
(symbols_with_pos_enabled): New boolean variable.
* src/fns.c (internal_equal, hash_lookup): Handle symbols with position.
* src/keyboard.c (recursive_edit_1): Bind Qsymbols_with_pos_enabled and
Qprint_symbols_bare to nil.
* src/lisp.h (lisp_h_PSEUDOVECTORP): New macro.
(lisp_h_BASE_EQ): New name for the former lisp_h_EQ.
(lisp_h_EQ): Extended to handle symbols with position.
(lisp_h_NILP): Now uses BASE_EQ rather than EQ.
(lisp_h_SYMBOL_WITH_POS_P, lisp_h_BARE_SYMBOL_P): New macros.
(lisp_h_SYMBOLP): Redefined to handle symbols with position.
(BARE_SYMBOL_P, BASE_EQ): New macros.
(SYMBOLP (macro)): Removed.
(SYMBOLP (function), XSYMBOL, make_lisp_symbol, builtin_lisp_symbol)
(c_symbol_p): Moved to later in file.
(struct Lisp_Symbol_With_Pos): New data type.
(pvec_type): PVEC_SYMBOL_WITH_POS: New type code.
(PSEUDOVECTORP): Redefined to use the lisp_h_PSEUDOVECTORP.
(BARE_SYMBOL_P, SYMBOL_WITH_POS_P, SYMBOLP, XSYMBOL_WITH_POS, XBARE_SYMBOL)
(XSYMBOL, make_lisp_symbol, builtin_lisp_symbol, c_symbol_p, CHECK_SYMBOL)
(BASE_EQ): New functions, or functions moved from earlier in the file.
(SYMBOL_WITH_POS_SYM, SYMBOL_WITH_POS_POS): New INLINE functions.
* src/lread.c (read0, read1, read_list, read_vector, read_internal_start)
(list2): Add a new bool parameter locate_syms.
(Fread_positioning_symbols): New function.
(Fread_from_string, read_internal_start, read0, read1, read_list): Pass around
suitable values for locate_syms.
(read1): Build symbols with position when locate_syms is true.
* src/print.c (print_vectorlike): Add handling for PVEC_SYMBOL_WITH_POS.
(print_object): Replace EQ with BASE_EQ.
(print_symbols_bare): New boolean variable.
* doc/lispref/control.texi (Destructuring with pcase Patterns):
Document this macro.
* lisp/emacs-lisp/pcase.el (pcase-setq): New macro. This macro is
the 'setq' equivalent of 'pcase-let'.
* test/lisp/emacs-lisp/pcase-tests.el (pcase-setq): Test this new
macro. (bug#49809).
Improve the handling of `or` patterns where not all sub-patterns bind the
same set of variables. This used to be "unsupported" and behaved in
somewhat unpredictable ways.
(pcase--expand): Rewrite.
(pcase-codegen): Delete.
* doc/lispref/control.texi (pcase Macro): Adjust accordingly.
Also remove the warning about "at least two" sub patterns.
These work fine, AFAICT, and if not we should fix it.
* test/lisp/emacs-lisp/pcase-tests.el (pcase-tests-or-vars): New test.
Revert commit a218c98615, but in order
to avoid the spurious warnings that this commit tried to squash,
keep track of the vars used during the match so as to add
corresponding annotations to explicitly silence the spurious warnings.
To do this, we change the VARS used in `pcase-u` (and throughout
the pcase code): they used to hold elements of the form (NAME . VAL)
and now they hold elements of the form (NAME VAL . USED).
(pcase--expand): Bind all vars instead of only those found via fgrep.
(pcase-codegen): Silence "unused var" warnings for those vars that have
already been referenced during the match itself.
(pcase--funcall, pcase--eval): Record the vars that are used.
(pcase--u1): Record the vars that are used via non-linear patterns.
* lisp/textmodes/mhtml-mode.el (mhtml-forward):
* lisp/vc/diff-mode.el (diff-goto-source): Silence newly
discovered warnings.
* test/lisp/emacs-lisp/pcase-tests.el (pcase-tests-bug46786): New test.
Instead of warning about unused vars during the analysis phase of
closure conversion, do it in the actual closure conversion by
annotating the code with "unused" warnings, so that the warnings
get emitted later by the bytecomp phase, like all other warnings,
at which point the line-number info is a bit less imprecise.
Take advantage of this change to wrap the expressions of unused
let-bound vars inside (ignore ...) so the byte-compiler can better
optimize them away.
Finally, promote `macroexp--warn-and-return` to "official" status
by removing its "--" marker.
(cconv-captured+mutated, cconv-lambda-candidates): Remove vars.
(cconv-var-classification): New var to replace them.
(cconv-warnings-only): Delete function.
(cconv--warn-unused-msg, cconv--var-classification): New functions.
(cconv--convert-funcbody): Add warnings for unused args.
(cconv-convert): Add warnings for unused vars in `let` and `condition-case`.
(cconv--analyze-use): Don't emit an "unused var" warning any more,
but instead remember the fact in `cconv-var-classification`.
* lisp/emacs-lisp/bytecomp.el (byte-compile-force-lexical-warnings):
Remove variable.
(byte-compile-preprocess): Remove corresponding case.
* lisp/emacs-lisp/pcase.el (pcase--if): Don't throw away `test` effects.
(\`):
* lisp/emacs-lisp/cl-macs.el (cl--do-arglist): Use `car-safe` instead
of `car`, so it can more easily be removed by the optimizer if the
result is not used.
* lisp/emacs-lisp/macroexp.el (macroexp--warn-wrap): New function.
(macroexp-warn-and-return): Rename from `macroexp--warn-and-return`.
This allows the use of (declare (debug ...)) in the lexical macros
defined with `cl-macrolet`. It also fixes the names used by Edebug
for the methods of `cl-generic` so it doesn't need to use gensym
and so they don't include the formal arg names any more.
* lisp/emacs-lisp/edebug.el (edebug--match-&-spec-op):
Rename from `edebug--handle-&-spec-op`.
(edebug--match-&-spec-op <&interpose>): Rename from `&lookup` and
generalize so it can let-bind dynamic variables around the rest of the parse.
(edebug-lexical-macro-ctx): Rename from `edebug--cl-macrolet-defs` and
make it into an alist.
(edebug-list-form-args): Use the specs from `edebug-lexical-macro-ctx`
when available.
(edebug--current-cl-macrolet-defs): Delete var.
(edebug-match-cl-macrolet-expr, edebug-match-cl-macrolet-name)
(edebug-match-cl-macrolet-body): Delete functions.
(def-declarations): Use new `&interpose`.
(edebug--match-declare-arg): Rename from `edebug--get-declare-spec` and
adjust to new calling convention.
* lisp/subr.el (def-edebug-elem-spec): Fix docstring.
(eval-after-load): Use `declare`.
* lisp/emacs-lisp/cl-generic.el: Fix Edebug names so we don't need
gensym any more and we only include the specializers but not the formal
arg names.
(cl--generic-edebug-name): New var.
(cl--generic-edebug-remember-name, cl--generic-edebug-make-name): New funs.
(cl-defgeneric, cl-defmethod): Use them.
* lisp/emacs-lisp/cl-macs.el: Add support for `debug` declarations in
`cl-macrolet`.
(cl-declarations-or-string):
Fix use of `lambda-doc` and allow use of `declare`.
(edebug-lexical-macro-ctx): Declare var.
(cl--edebug-macrolet-interposer): New function.
(cl-macrolet): Use it to pass the right `lexical-macro-ctx` to the body.
* lisp/emacs-lisp/pcase.el (pcase-PAT): Use new `&interpose`.
(pcase--edebug-match-pat-args): Rename from `pcase--get-edebug-spec` and
adjust to new calling convention.
* test/lisp/emacs-lisp/cl-generic-tests.el (cl-defgeneric/edebug/method):
Adjust to the new names.
* test/lisp/emacs-lisp/edebug-tests.el (edebug-cl-defmethod-qualifier)
(edebug-tests-cl-flet): Adjust to the new names.
* doc/lispref/edebug.texi (Specification List): Document &interpose.
The `edebug-form-spec` symbol property was used both to map forms's
head symbol to the corresponding spec, and to map spec element names
to their expansion.
This lead to name conflicts which break instrumentation of examples such as
(cl-flet ((gate (x) x)) (gate 4))
because of the Edebug spec element `gate`.
So introduce a new symbol property `edebug-elem-spec`.
* lisp/subr.el (def-edebug-elem-spec): New function.
* lisp/emacs-lisp/edebug.el (edebug--get-elem-spec): New function.
(edebug-match-symbol): Use it.
(Core Edebug elems): Put them on `edebug-elem-spec` instead of
`edebug-form-spec`.
(ELisp special forms): Set their `edebug-form-spec` via dolist.
(Other non-core Edebug elems): Use `def-edebug-elem-spec`.
(edebug-\`): Use `declare`.
* lisp/emacs-lisp/pcase.el (pcase-PAT, pcase-FUN, pcase-QPAT):
* lisp/skeleton.el (skeleton-edebug-spec):
* lisp/emacs-lisp/cl-macs.el: Use `def-edebug-elem-spec`.
* test/lisp/emacs-lisp/edebug-tests.el
(edebug-tests--conflicting-internal-names): New test.
* test/lisp/emacs-lisp/edebug-resources/edebug-test-code.el
(edebug-test-code-cl-flet1): New test case.
* doc/lispref/edebug.texi (Specification List): Add `def-edebug-elem-spec`.
(Specification Examples): Use it.
* doc/lispref/loading.texi (Hooks for Loading): Avoid the use of
`def-edebug-spec` in example (better use `debug` declaration).
Move all definitions under the `edebug-` prefix.
(edebug-get-spec): Rename from `get-edebug-spec`.
(edebug-move-cursor): Use `cl-callf`.
(edebug-spec-p): Remove unused function.
(def-edebug-spec, edebug-spec-list, edebug-spec): Remove unused specs
(nothing in there gets instrumented anyway).
(edebug-tracing): Use `declare`.
(edebug-cancel-on-entry): Rename from `cancel-edebug-on-entry`.
(edebug-global-prefix): Rename from `global-edebug-prefix`.
(edebug-global-map): Rename from `global-edebug-map`.
* lisp/emacs-lisp/pcase.el (pcase-PAT): Remove `let`.
(let): Use `declare` instead.
(pcase--edebug-match-macro): Use new name `edebug-get-spec`.
(pcase--split-pred, pcase--funcall): Adjust for `not`.
(pcase--get-macroexpander): New function.
(pcase--edebug-match-macro, pcase--make-docstring)
(pcase--macroexpand): Use it.
* lisp/emacs-lisp/radix-tree.el (radix-tree-leaf): Use it!
* doc/lispref/control.texi (The @code{pcase} macro): Document it.
* lisp/emacs-lisp/ert.el (ert--explain-equal-rec): Remove redundant test.