diff options
| author | Mattias EngdegÄrd | 2024-03-10 13:18:22 +0100 |
|---|---|---|
| committer | Mattias EngdegÄrd | 2024-03-29 11:39:38 +0100 |
| commit | 1232ab31c656b8564984a758957466f90ac10501 (patch) | |
| tree | 38a7774207a5ac8dba2612bef9a6a39f3cd0d658 /test/src/fns-tests.el | |
| parent | c3684b97885c5a1f4d0713ff45c7395e9a4c6e8a (diff) | |
| download | emacs-1232ab31c656b8564984a758957466f90ac10501.tar.gz emacs-1232ab31c656b8564984a758957466f90ac10501.zip | |
Add `value<` (bug#69709)
It's a general-purpose polymorphic ordering function, like `<` but
for any two values of the same type.
* src/data.c (syms_of_data): Add the `type-mismatch` error.
(bits_word_to_host_endian): Move...
* src/lisp.h (bits_word_to_host_endian): ...here, and declare inline.
* src/fns.c (Fstring_lessp): Extract the bulk of this function to...
(string_cmp): ...this 3-way comparison function, for use elsewhere.
(bool_vector_cmp, value_cmp, Fvaluelt): New.
* lisp/emacs-lisp/byte-opt.el (side-effect-free-fns, pure-fns):
Add `value<`, which is pure and side-effect-free.
* test/src/fns-tests.el (fns-value<-ordered, fns-value<-unordered)
(fns-value<-type-mismatch, fns-value<-symbol-with-pos)
(fns-value<-circle, ert-deftest fns-value<-bool-vector): New tests.
* doc/lispref/sequences.texi (Sequence Functions):
* doc/lispref/numbers.texi (Comparison of Numbers):
* doc/lispref/strings.texi (Text Comparison):
Document the new value< function.
* etc/NEWS: Announce.
Diffstat (limited to 'test/src/fns-tests.el')
| -rw-r--r-- | test/src/fns-tests.el | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/test/src/fns-tests.el b/test/src/fns-tests.el index 7437c07f156..844000cdc76 100644 --- a/test/src/fns-tests.el +++ b/test/src/fns-tests.el | |||
| @@ -1513,4 +1513,222 @@ | |||
| 1513 | (should-error (copy-alist "abc") | 1513 | (should-error (copy-alist "abc") |
| 1514 | :type 'wrong-type-argument)) | 1514 | :type 'wrong-type-argument)) |
| 1515 | 1515 | ||
| 1516 | (ert-deftest fns-value<-ordered () | ||
| 1517 | ;; values (X . Y) where X<Y | ||
| 1518 | (let* ((big (* 10 most-positive-fixnum)) | ||
| 1519 | (buf1 (get-buffer-create " *one*")) | ||
| 1520 | (buf2 (get-buffer-create " *two*")) | ||
| 1521 | (buf3 (get-buffer-create " *three*")) | ||
| 1522 | (_ (progn (with-current-buffer buf1 (insert (make-string 20 ?a))) | ||
| 1523 | (with-current-buffer buf2 (insert (make-string 20 ?b))))) | ||
| 1524 | (mark1 (set-marker (make-marker) 12 buf1)) | ||
| 1525 | (mark2 (set-marker (make-marker) 13 buf1)) | ||
| 1526 | (mark3 (set-marker (make-marker) 12 buf2)) | ||
| 1527 | (mark4 (set-marker (make-marker) 13 buf2)) | ||
| 1528 | (proc1 (make-pipe-process :name " *proc one*")) | ||
| 1529 | (proc2 (make-pipe-process :name " *proc two*"))) | ||
| 1530 | (kill-buffer buf3) | ||
| 1531 | (unwind-protect | ||
| 1532 | (dolist (c | ||
| 1533 | `( | ||
| 1534 | ;; fixnums | ||
| 1535 | (1 . 2) (-2 . -1) (-2 . 1) (-1 . 2) | ||
| 1536 | ;; bignums | ||
| 1537 | (,big . ,(1+ big)) (,(- big) . ,big) | ||
| 1538 | (,(- -1 big) . ,(- big)) | ||
| 1539 | ;; fixnums/bignums | ||
| 1540 | (1 . ,big) (-1 . ,big) (,(- big) . -1) (,(- big) . 1) | ||
| 1541 | ;; floats | ||
| 1542 | (1.5 . 1.6) (-1.3 . -1.2) (-13.0 . 12.0) | ||
| 1543 | ;; floats/fixnums | ||
| 1544 | (1 . 1.1) (1.9 . 2) (-2.0 . 1) (-2 . 1.0) | ||
| 1545 | ;; floats/bignums | ||
| 1546 | (,big . ,(float (* 2 big))) (,(float big) . ,(* 2 big)) | ||
| 1547 | ;; symbols | ||
| 1548 | (a . b) (nil . nix) (b . ba) (## . a) (A . a) | ||
| 1549 | (#:a . #:b) (a . #:b) (#:a . b) | ||
| 1550 | ;; strings | ||
| 1551 | ("" . "a") ("a" . "b") ("A" . "a") ("abc" . "abd") | ||
| 1552 | ("b" . "ba") | ||
| 1553 | |||
| 1554 | ;; lists | ||
| 1555 | ((1 2 3) . (2 3 4)) ((2) . (2 1)) (() . (0)) | ||
| 1556 | ((1 2 3) . (1 3)) ((1 2 3) . (1 3 2)) | ||
| 1557 | (((b a) (c d) e) . ((b a) (c d) f)) | ||
| 1558 | (((b a) (c D) e) . ((b a) (c d) e)) | ||
| 1559 | (((b a) (c d () x) e) . ((b a) (c d (1) x) e)) | ||
| 1560 | ((1 . 2) . (1 . 3)) ((1 2 . 3) . (1 2 . 4)) | ||
| 1561 | |||
| 1562 | ;; vectors | ||
| 1563 | ([1 2 3] . [2 3 4]) ([2] . [2 1]) ([] . [0]) | ||
| 1564 | ([1 2 3] . [1 3]) ([1 2 3] . [1 3 2]) | ||
| 1565 | ([[b a] [c d] e] . [[b a] [c d] f]) | ||
| 1566 | ([[b a] [c D] e] . [[b a] [c d] e]) | ||
| 1567 | ([[b a] [c d [] x] e] . [[b a] [c d [1] x] e]) | ||
| 1568 | |||
| 1569 | ;; bool-vectors | ||
| 1570 | (,(bool-vector) . ,(bool-vector nil)) | ||
| 1571 | (,(bool-vector nil) . ,(bool-vector t)) | ||
| 1572 | (,(bool-vector t nil t nil) . ,(bool-vector t nil t t)) | ||
| 1573 | (,(bool-vector t nil t) . ,(bool-vector t nil t nil)) | ||
| 1574 | |||
| 1575 | ;; records | ||
| 1576 | (#s(a 2 3) . #s(b 3 4)) (#s(b) . #s(b a)) | ||
| 1577 | (#s(a 2 3) . #s(a 3)) (#s(a 2 3) . #s(a 3 2)) | ||
| 1578 | (#s(#s(b a) #s(c d) e) . #s(#s(b a) #s(c d) f)) | ||
| 1579 | (#s(#s(b a) #s(c D) e) . #s(#s(b a) #s(c d) e)) | ||
| 1580 | (#s(#s(b a) #s(c d #s(u) x) e) | ||
| 1581 | . #s(#s(b a) #s(c d #s(v) x) e)) | ||
| 1582 | |||
| 1583 | ;; markers | ||
| 1584 | (,mark1 . ,mark2) (,mark1 . ,mark3) (,mark1 . ,mark4) | ||
| 1585 | (,mark2 . ,mark3) (,mark2 . ,mark4) (,mark3 . ,mark4) | ||
| 1586 | |||
| 1587 | ;; buffers | ||
| 1588 | (,buf1 . ,buf2) (,buf3 . ,buf1) (,buf3 . ,buf2) | ||
| 1589 | |||
| 1590 | ;; processes | ||
| 1591 | (,proc1 . ,proc2) | ||
| 1592 | )) | ||
| 1593 | (let ((x (car c)) | ||
| 1594 | (y (cdr c))) | ||
| 1595 | (should (value< x y)) | ||
| 1596 | (should-not (value< y x)) | ||
| 1597 | (should-not (value< x x)) | ||
| 1598 | (should-not (value< y y)))) | ||
| 1599 | |||
| 1600 | (delete-process proc2) | ||
| 1601 | (delete-process proc1) | ||
| 1602 | (kill-buffer buf2) | ||
| 1603 | (kill-buffer buf1)))) | ||
| 1604 | |||
| 1605 | (ert-deftest fns-value<-unordered () | ||
| 1606 | ;; values (X . Y) where neither X<Y nor Y<X | ||
| 1607 | |||
| 1608 | (let ((buf1 (get-buffer-create " *one*")) | ||
| 1609 | (buf2 (get-buffer-create " *two*"))) | ||
| 1610 | (kill-buffer buf2) | ||
| 1611 | (kill-buffer buf1) | ||
| 1612 | (dolist (c `( | ||
| 1613 | ;; numbers | ||
| 1614 | (0 . 0.0) (0 . -0.0) (0.0 . -0.0) | ||
| 1615 | |||
| 1616 | ;; symbols | ||
| 1617 | (a . #:a) | ||
| 1618 | |||
| 1619 | ;; (dead) buffers | ||
| 1620 | (,buf1 . ,buf2) | ||
| 1621 | |||
| 1622 | ;; unordered types | ||
| 1623 | (,(make-hash-table) . ,(make-hash-table)) | ||
| 1624 | (,(obarray-make) . ,(obarray-make)) | ||
| 1625 | ;; FIXME: more? | ||
| 1626 | )) | ||
| 1627 | (let ((x (car c)) | ||
| 1628 | (y (cdr c))) | ||
| 1629 | (should-not (value< x y)) | ||
| 1630 | (should-not (value< y x)))))) | ||
| 1631 | |||
| 1632 | (ert-deftest fns-value<-type-mismatch () | ||
| 1633 | ;; values of disjoint (incomparable) types | ||
| 1634 | (let ((incomparable | ||
| 1635 | `( 1 a "a" (a b) [a b] ,(bool-vector nil t) #s(a b) | ||
| 1636 | ,(make-char-table 'test) | ||
| 1637 | ,(make-hash-table) | ||
| 1638 | ,(obarray-make) | ||
| 1639 | ;; FIXME: more? | ||
| 1640 | ))) | ||
| 1641 | (let ((tail incomparable)) | ||
| 1642 | (while tail | ||
| 1643 | (let ((x (car tail))) | ||
| 1644 | (dolist (y (cdr tail)) | ||
| 1645 | (should-error (value< x y) :type 'type-mismatch) | ||
| 1646 | (should-error (value< y x) :type 'type-mismatch))) | ||
| 1647 | (setq tail (cdr tail)))))) | ||
| 1648 | |||
| 1649 | (ert-deftest fns-value<-symbol-with-pos () | ||
| 1650 | ;; values (X . Y) where X<Y | ||
| 1651 | (let* ((a-sp-1 (position-symbol 'a 1)) | ||
| 1652 | (a-sp-2 (position-symbol 'a 2)) | ||
| 1653 | (b-sp-1 (position-symbol 'b 1)) | ||
| 1654 | (b-sp-2 (position-symbol 'b 2))) | ||
| 1655 | |||
| 1656 | (dolist (swp '(nil t)) | ||
| 1657 | (let ((symbols-with-pos-enabled swp)) | ||
| 1658 | ;; Enabled or not, they compare by name. | ||
| 1659 | (dolist (c `((,a-sp-1 . ,b-sp-1) (,a-sp-1 . ,b-sp-2) | ||
| 1660 | (,a-sp-2 . ,b-sp-1) (,a-sp-2 . ,b-sp-2))) | ||
| 1661 | (let ((x (car c)) | ||
| 1662 | (y (cdr c))) | ||
| 1663 | (should (value< x y)) | ||
| 1664 | (should-not (value< y x)) | ||
| 1665 | (should-not (value< x x)) | ||
| 1666 | (should-not (value< y y)))) | ||
| 1667 | (should-not (value< a-sp-1 a-sp-2)) | ||
| 1668 | (should-not (value< a-sp-2 a-sp-1)))) | ||
| 1669 | |||
| 1670 | ;; When disabled, symbol-with-pos and symbols do not compare. | ||
| 1671 | (should-error (value< a-sp-1 'a) :type 'type-mismatch) | ||
| 1672 | (should-error (value< 'a a-sp-1) :type 'type-mismatch) | ||
| 1673 | |||
| 1674 | (let ((symbols-with-pos-enabled t)) | ||
| 1675 | ;; When enabled, a symbol-with-pos compares as a plain symbol. | ||
| 1676 | (dolist (c `((,a-sp-1 . b) (a . ,b-sp-1))) | ||
| 1677 | (let ((x (car c)) | ||
| 1678 | (y (cdr c))) | ||
| 1679 | (should (value< x y)) | ||
| 1680 | (should-not (value< y x)) | ||
| 1681 | (should-not (value< x x)) | ||
| 1682 | (should-not (value< y y)))) | ||
| 1683 | (should-not (value< a-sp-1 'a)) | ||
| 1684 | (should-not (value< 'a a-sp-1))))) | ||
| 1685 | |||
| 1686 | (ert-deftest fns-value<-circle () | ||
| 1687 | ;; Check that we at least don't hang when comparing two circular lists. | ||
| 1688 | (let ((a (number-sequence 1 5)) | ||
| 1689 | (b (number-sequence 1 5))) | ||
| 1690 | (setcdr (last a) (nthcdr 2 a)) | ||
| 1691 | (setcdr (last b) (nthcdr 2 b)) | ||
| 1692 | (should-error (value< a b :type 'circular)) | ||
| 1693 | (should-error (value< b a :type 'circular)))) | ||
| 1694 | |||
| 1695 | (ert-deftest fns-value<-bool-vector () | ||
| 1696 | ;; More thorough test of `value<' for bool-vectors. | ||
| 1697 | (random "my seed") | ||
| 1698 | (dolist (na '(0 1 5 8 9 32 63 64 65 200 1001 1024)) | ||
| 1699 | (let ((a (make-bool-vector na nil))) | ||
| 1700 | (dotimes (i na) | ||
| 1701 | (aset a i (zerop (random 2)))) | ||
| 1702 | (dolist (nb '(0 1 5 8 9 32 63 64 65 200 1001 1024)) | ||
| 1703 | (when (<= nb na) | ||
| 1704 | (let ((b (make-bool-vector nb nil))) | ||
| 1705 | (dotimes (i nb) | ||
| 1706 | (aset b i (aref a i))) | ||
| 1707 | ;; `b' is now a prefix of `a'. | ||
| 1708 | (should-not (value< a b)) | ||
| 1709 | (cond ((= nb na) | ||
| 1710 | (should (equal a b)) | ||
| 1711 | (should-not (value< b a))) | ||
| 1712 | (t | ||
| 1713 | (should-not (equal a b)) | ||
| 1714 | (should (value< b a)))) | ||
| 1715 | (unless (zerop nb) | ||
| 1716 | ;; Flip random bits in `b' and check how it affects the order. | ||
| 1717 | (dotimes (_ 3) | ||
| 1718 | (let ((i (random nb))) | ||
| 1719 | (let ((val (aref b i))) | ||
| 1720 | (aset b i (not val)) | ||
| 1721 | (should-not (equal a b)) | ||
| 1722 | (cond | ||
| 1723 | (val | ||
| 1724 | ;; t -> nil: `b' is now always a proper prefix of `a'. | ||
| 1725 | (should-not (value< a b)) | ||
| 1726 | (should (value< b a))) | ||
| 1727 | (t | ||
| 1728 | ;; nil -> t: `a' is now less than `b'. | ||
| 1729 | (should (value< a b)) | ||
| 1730 | (should-not (value< b a)))) | ||
| 1731 | ;; Undo the flip. | ||
| 1732 | (aset b i val))))))))))) | ||
| 1733 | |||
| 1516 | ;;; fns-tests.el ends here | 1734 | ;;; fns-tests.el ends here |