diff options
| author | Alan Mackenzie | 2023-09-04 12:51:24 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2023-09-04 12:51:24 +0000 |
| commit | afcb6d0bc7abcdbca6b18d020deeff24d1ad197f (patch) | |
| tree | 1561281df0284ced50d19005770c00023e7a617e | |
| parent | 55a0f0e047034b3a458b6fdbe245f33b83fd88b0 (diff) | |
| download | emacs-afcb6d0bc7abcdbca6b18d020deeff24d1ad197f.tar.gz emacs-afcb6d0bc7abcdbca6b18d020deeff24d1ad197f.zip | |
Correct the handling of symbols with position in equal
* src/fns.c (internal_equal): Only regard symbols with position
as their symbols when symbols-with-pos-enabled is non-nil.
* doc/lispref/symbols.texi (Symbols with Position): Expand the
description of symbols with position, in particular the way
they work with eq and equal.
* doc/lispref/objects.texi (Equality Predicates): Describe how
eq and equal handle symbols with position.
* test/src/fns-tests.el (fns-tests-equal-symbols-with-position):
New tests for symbols with position.
| -rw-r--r-- | doc/lispref/objects.texi | 11 | ||||
| -rw-r--r-- | doc/lispref/symbols.texi | 40 | ||||
| -rw-r--r-- | src/fns.c | 20 | ||||
| -rw-r--r-- | test/src/fns-tests.el | 20 |
4 files changed, 72 insertions, 19 deletions
diff --git a/doc/lispref/objects.texi b/doc/lispref/objects.texi index ad079e0d63a..784d59720ed 100644 --- a/doc/lispref/objects.texi +++ b/doc/lispref/objects.texi | |||
| @@ -2206,6 +2206,10 @@ and the same non-fixnum numeric type, then they might or might not be | |||
| 2206 | the same object, and @code{eq} returns @code{t} or @code{nil} | 2206 | the same object, and @code{eq} returns @code{t} or @code{nil} |
| 2207 | depending on whether the Lisp interpreter created one object or two. | 2207 | depending on whether the Lisp interpreter created one object or two. |
| 2208 | 2208 | ||
| 2209 | If @var{object1} or @var{object2} is a symbol with position, @code{eq} | ||
| 2210 | regards it as its bare symbol when @code{symbols-with-pos-enabled} is | ||
| 2211 | non-@code{nil} (@pxref{Symbols with Position}). | ||
| 2212 | |||
| 2209 | @example | 2213 | @example |
| 2210 | @group | 2214 | @group |
| 2211 | (eq 'foo 'foo) | 2215 | (eq 'foo 'foo) |
| @@ -2363,6 +2367,13 @@ same sequence of character codes and all these codes are in the range | |||
| 2363 | The @code{equal} function recursively compares the contents of objects | 2367 | The @code{equal} function recursively compares the contents of objects |
| 2364 | if they are integers, strings, markers, vectors, bool-vectors, | 2368 | if they are integers, strings, markers, vectors, bool-vectors, |
| 2365 | byte-code function objects, char-tables, records, or font objects. | 2369 | byte-code function objects, char-tables, records, or font objects. |
| 2370 | |||
| 2371 | If @var{object1} or @var{object2} is a symbol with position, | ||
| 2372 | @code{equal} regards it as its bare symbol when | ||
| 2373 | @code{symbols-with-pos-enabled} is non-@code{nil}. Otherwise | ||
| 2374 | @code{equal} compares two symbols with position by recursively | ||
| 2375 | comparing their components. @xref{Symbols with Position}. | ||
| 2376 | |||
| 2366 | Other objects are considered @code{equal} only if they are @code{eq}. | 2377 | Other objects are considered @code{equal} only if they are @code{eq}. |
| 2367 | For example, two distinct buffers are never considered @code{equal}, | 2378 | For example, two distinct buffers are never considered @code{equal}, |
| 2368 | even if their textual contents are the same. | 2379 | even if their textual contents are the same. |
diff --git a/doc/lispref/symbols.texi b/doc/lispref/symbols.texi index 34db0caf3a8..1f3b677d7fb 100644 --- a/doc/lispref/symbols.texi +++ b/doc/lispref/symbols.texi | |||
| @@ -783,10 +783,15 @@ Symbol forms whose names start with @samp{#_} are not transformed. | |||
| 783 | 783 | ||
| 784 | @cindex bare symbol | 784 | @cindex bare symbol |
| 785 | A @dfn{symbol with position} is a symbol, the @dfn{bare symbol}, | 785 | A @dfn{symbol with position} is a symbol, the @dfn{bare symbol}, |
| 786 | together with an unsigned integer called the @dfn{position}. These | 786 | together with an unsigned integer called the @dfn{position}. Symbols |
| 787 | objects are intended for use by the byte compiler, which records in | 787 | with position don't themselves have entries in the obarray (though |
| 788 | them the position of each symbol occurrence and uses those positions | 788 | their bare symbols do; @pxref{Creating Symbols}). |
| 789 | in warning and error messages. | 789 | |
| 790 | Symbols with position are for the use of the byte compiler, which | ||
| 791 | records in them the position of each symbol occurrence and uses those | ||
| 792 | positions in warning and error messages. They shouldn't normally be | ||
| 793 | used otherwise. Doing so can cause unexpected results with basic | ||
| 794 | Emacs functions such as @code{eq} and @code{equal}. | ||
| 790 | 795 | ||
| 791 | The printed representation of a symbol with position uses the hash | 796 | The printed representation of a symbol with position uses the hash |
| 792 | notation outlined in @ref{Printed Representation}. It looks like | 797 | notation outlined in @ref{Printed Representation}. It looks like |
| @@ -798,11 +803,20 @@ the compiled Lisp file. | |||
| 798 | 803 | ||
| 799 | For most purposes, when the flag variable | 804 | For most purposes, when the flag variable |
| 800 | @code{symbols-with-pos-enabled} is non-@code{nil}, symbols with | 805 | @code{symbols-with-pos-enabled} is non-@code{nil}, symbols with |
| 801 | positions behave just as bare symbols do. For example, @samp{(eq | 806 | positions behave just as their bare symbols would. For example, |
| 802 | #<symbol foo at 12345> foo)} has a value @code{t} when that variable | 807 | @samp{(eq #<symbol foo at 12345> foo)} has a value @code{t} when the |
| 803 | is set (but @code{nil} when it isn't set). Most of the time in Emacs this | 808 | variable is set; likewise, @code{equal} will treat a symbol with |
| 804 | variable is @code{nil}, but the byte compiler binds it to @code{t} | 809 | position argument as its bare symbol. |
| 805 | when it runs. | 810 | |
| 811 | When @code{symbols-with-pos-enabled} is @code{nil}, any symbols with | ||
| 812 | position continue to exist, but do not behave as symbols, or have the | ||
| 813 | other useful properties outlined in the previous paragraph. @code{eq} | ||
| 814 | returns @code{t} when given identical arguments, and @code{equal} | ||
| 815 | returns @code{t} when given arguments with @code{equal} components. | ||
| 816 | |||
| 817 | Most of the time in Emacs @code{symbols-with-pos-enabled} is | ||
| 818 | @code{nil}, but the byte compiler and the native compiler bind it to | ||
| 819 | @code{t} when they run. | ||
| 806 | 820 | ||
| 807 | Typically, symbols with position are created by the byte compiler | 821 | Typically, symbols with position are created by the byte compiler |
| 808 | calling the reader function @code{read-positioning-symbols} | 822 | calling the reader function @code{read-positioning-symbols} |
| @@ -810,17 +824,17 @@ calling the reader function @code{read-positioning-symbols} | |||
| 810 | @code{position-symbol}. | 824 | @code{position-symbol}. |
| 811 | 825 | ||
| 812 | @defvar symbols-with-pos-enabled | 826 | @defvar symbols-with-pos-enabled |
| 813 | When this variable is non-@code{nil}, symbols with position behave | 827 | When this variable is non-@code{nil}, a symbol with position behaves |
| 814 | like the contained bare symbol. Emacs runs a little more slowly in | 828 | like the contained bare symbol. Emacs runs a little more slowly in |
| 815 | this case. | 829 | this case. |
| 816 | @end defvar | 830 | @end defvar |
| 817 | 831 | ||
| 818 | @defvar print-symbols-bare | 832 | @defvar print-symbols-bare |
| 819 | When bound to non-@code{nil}, the Lisp printer prints only the bare symbol of | 833 | When bound to non-@code{nil}, the Lisp printer prints only the bare |
| 820 | a symbol with position, ignoring the position. | 834 | symbol of a symbol with position, ignoring the position. |
| 821 | @end defvar | 835 | @end defvar |
| 822 | 836 | ||
| 823 | @defun symbol-with-pos-p symbol. | 837 | @defun symbol-with-pos-p symbol |
| 824 | This function returns @code{t} if @var{symbol} is a symbol with | 838 | This function returns @code{t} if @var{symbol} is a symbol with |
| 825 | position, @code{nil} otherwise. | 839 | position, @code{nil} otherwise. |
| 826 | @end defun | 840 | @end defun |
| @@ -2774,10 +2774,13 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, | |||
| 2774 | 2774 | ||
| 2775 | /* A symbol with position compares the contained symbol, and is | 2775 | /* A symbol with position compares the contained symbol, and is |
| 2776 | `equal' to the corresponding ordinary symbol. */ | 2776 | `equal' to the corresponding ordinary symbol. */ |
| 2777 | if (SYMBOL_WITH_POS_P (o1)) | 2777 | if (symbols_with_pos_enabled) |
| 2778 | o1 = SYMBOL_WITH_POS_SYM (o1); | 2778 | { |
| 2779 | if (SYMBOL_WITH_POS_P (o2)) | 2779 | if (SYMBOL_WITH_POS_P (o1)) |
| 2780 | o2 = SYMBOL_WITH_POS_SYM (o2); | 2780 | o1 = SYMBOL_WITH_POS_SYM (o1); |
| 2781 | if (SYMBOL_WITH_POS_P (o2)) | ||
| 2782 | o2 = SYMBOL_WITH_POS_SYM (o2); | ||
| 2783 | } | ||
| 2781 | 2784 | ||
| 2782 | if (BASE_EQ (o1, o2)) | 2785 | if (BASE_EQ (o1, o2)) |
| 2783 | return true; | 2786 | return true; |
| @@ -2825,8 +2828,8 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, | |||
| 2825 | if (ASIZE (o2) != size) | 2828 | if (ASIZE (o2) != size) |
| 2826 | return false; | 2829 | return false; |
| 2827 | 2830 | ||
| 2828 | /* Compare bignums, overlays, markers, and boolvectors | 2831 | /* Compare bignums, overlays, markers, boolvectors, and |
| 2829 | specially, by comparing their values. */ | 2832 | symbols with position specially, by comparing their values. */ |
| 2830 | if (BIGNUMP (o1)) | 2833 | if (BIGNUMP (o1)) |
| 2831 | return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; | 2834 | return mpz_cmp (*xbignum_val (o1), *xbignum_val (o2)) == 0; |
| 2832 | if (OVERLAYP (o1)) | 2835 | if (OVERLAYP (o1)) |
| @@ -2858,6 +2861,11 @@ internal_equal (Lisp_Object o1, Lisp_Object o2, enum equal_kind equal_kind, | |||
| 2858 | if (TS_NODEP (o1)) | 2861 | if (TS_NODEP (o1)) |
| 2859 | return treesit_node_eq (o1, o2); | 2862 | return treesit_node_eq (o1, o2); |
| 2860 | #endif | 2863 | #endif |
| 2864 | if (SYMBOL_WITH_POS_P(o1)) /* symbols_with_pos_enabled is false. */ | ||
| 2865 | return (BASE_EQ (XSYMBOL_WITH_POS (o1)->sym, | ||
| 2866 | XSYMBOL_WITH_POS (o2)->sym) | ||
| 2867 | && BASE_EQ (XSYMBOL_WITH_POS (o1)->pos, | ||
| 2868 | XSYMBOL_WITH_POS (o2)->pos)); | ||
| 2861 | 2869 | ||
| 2862 | /* Aside from them, only true vectors, char-tables, compiled | 2870 | /* Aside from them, only true vectors, char-tables, compiled |
| 2863 | functions, and fonts (font-spec, font-entity, font-object) | 2871 | functions, and fonts (font-spec, font-entity, font-object) |
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 79ae4393f40..9c09e4f0c33 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el | |||
| @@ -98,6 +98,26 @@ | |||
| 98 | (should-not (equal-including-properties #("a" 0 1 (k "v")) | 98 | (should-not (equal-including-properties #("a" 0 1 (k "v")) |
| 99 | #("b" 0 1 (k "v"))))) | 99 | #("b" 0 1 (k "v"))))) |
| 100 | 100 | ||
| 101 | (ert-deftest fns-tests-equal-symbols-with-position () | ||
| 102 | "Test `eq' and `equal' on symbols with position." | ||
| 103 | (let ((foo1 (position-symbol 'foo 42)) | ||
| 104 | (foo2 (position-symbol 'foo 666)) | ||
| 105 | (foo3 (position-symbol 'foo 42))) | ||
| 106 | (let (symbols-with-pos-enabled) | ||
| 107 | (should (eq foo1 foo1)) | ||
| 108 | (should (equal foo1 foo1)) | ||
| 109 | (should-not (eq foo1 foo2)) | ||
| 110 | (should-not (equal foo1 foo2)) | ||
| 111 | (should-not (eq foo1 foo3)) | ||
| 112 | (should (equal foo1 foo3))) | ||
| 113 | (let ((symbols-with-pos-enabled t)) | ||
| 114 | (should (eq foo1 foo1)) | ||
| 115 | (should (equal foo1 foo1)) | ||
| 116 | (should (eq foo1 foo2)) | ||
| 117 | (should (equal foo1 foo2)) | ||
| 118 | (should (eq foo1 foo3)) | ||
| 119 | (should (equal foo1 foo3))))) | ||
| 120 | |||
| 101 | (ert-deftest fns-tests-reverse () | 121 | (ert-deftest fns-tests-reverse () |
| 102 | (should-error (reverse)) | 122 | (should-error (reverse)) |
| 103 | (should-error (reverse 1)) | 123 | (should-error (reverse 1)) |