comparison src/fns.c @ 5285:99de5fd48e87

Tighten up Common Lisp compatibility, #'butlast, #'nbutlast, #'tailp, #'ldiff lisp/ChangeLog addition: 2010-10-14 Aidan Kehoe <kehoea@parhasard.net> * byte-optimize.el (side-effect-free-fns): * cl-macs.el (remf, getf): * cl-extra.el (tailp, cl-set-getf, cl-do-remf): * cl.el (ldiff, endp): Tighten up Common Lisp compatibility for #'ldiff, #'endp, #'tailp; add circularity checking for the first two. #'cl-set-getf and #'cl-do-remf were Lisp implementations of #'plist-put and #'plist-remprop; change the names to aliases, changes the macros that use them to using #'plist-put and #'plist-remprop directly. src/ChangeLog addition: 2010-10-14 Aidan Kehoe <kehoea@parhasard.net> * fns.c (Fnbutlast, Fbutlast): Tighten up Common Lisp compatibility for these two functions; they need to operate on dotted lists without erroring. tests/ChangeLog addition: 2010-10-14 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el (x): Test #'nbutlast, #'butlast with dotted lists. Check that #'ldiff and #'tailp don't hang on circular lists; check that #'tailp returns t with circular lists when that is appropriate. Test them both with dotted lists.
author Aidan Kehoe <kehoea@parhasard.net>
date Thu, 14 Oct 2010 18:50:38 +0100
parents be436ac36ba4
children 28651c24b3f8 b9167d522a9a
comparison
equal deleted inserted replaced
5284:d27c1ee1943b 5285:99de5fd48e87
1568 return retval; 1568 return retval;
1569 } 1569 }
1570 1570
1571 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /* 1571 DEFUN ("nbutlast", Fnbutlast, 1, 2, 0, /*
1572 Modify LIST to remove the last N (default 1) elements. 1572 Modify LIST to remove the last N (default 1) elements.
1573
1573 If LIST has N or fewer elements, nil is returned and LIST is unmodified. 1574 If LIST has N or fewer elements, nil is returned and LIST is unmodified.
1575 Otherwise, LIST may be dotted, but not circular.
1574 */ 1576 */
1575 (list, n)) 1577 (list, n))
1576 { 1578 {
1577 EMACS_INT int_n; 1579 Elemcount int_n = 1;
1578 1580
1579 CHECK_LIST (list); 1581 CHECK_LIST (list);
1580 1582
1581 if (NILP (n)) 1583 if (!NILP (n))
1582 int_n = 1;
1583 else
1584 { 1584 {
1585 CHECK_NATNUM (n); 1585 CHECK_NATNUM (n);
1586 int_n = XINT (n); 1586 int_n = XINT (n);
1587 } 1587 }
1588 1588
1589 { 1589 if (CONSP (list))
1590 Lisp_Object last_cons = list; 1590 {
1591 1591 Lisp_Object last_cons = list;
1592 EXTERNAL_LIST_LOOP_1 (list) 1592
1593 { 1593 EXTERNAL_LIST_LOOP_3 (elt, list, tail)
1594 if (int_n-- < 0) 1594 {
1595 last_cons = XCDR (last_cons); 1595 if (int_n-- < 0)
1596 } 1596 {
1597 1597 last_cons = XCDR (last_cons);
1598 if (int_n >= 0) 1598 }
1599 return Qnil; 1599
1600 1600 if (!CONSP (XCDR (tail)))
1601 XCDR (last_cons) = Qnil; 1601 {
1602 return list; 1602 break;
1603 } 1603 }
1604 }
1605
1606 if (int_n >= 0)
1607 {
1608 return Qnil;
1609 }
1610
1611 XCDR (last_cons) = Qnil;
1612 }
1613
1614 return list;
1604 } 1615 }
1605 1616
1606 DEFUN ("butlast", Fbutlast, 1, 2, 0, /* 1617 DEFUN ("butlast", Fbutlast, 1, 2, 0, /*
1607 Return a copy of LIST with the last N (default 1) elements removed. 1618 Return a copy of LIST with the last N (default 1) elements removed.
1619
1608 If LIST has N or fewer elements, nil is returned. 1620 If LIST has N or fewer elements, nil is returned.
1621 Otherwise, LIST may be dotted, but not circular, and `(butlast LIST 0)'
1622 converts a dotted into a true list.
1609 */ 1623 */
1610 (list, n)) 1624 (list, n))
1611 { 1625 {
1612 EMACS_INT int_n; 1626 Lisp_Object retval = Qnil, retval_tail = Qnil;
1627 Elemcount int_n = 1;
1613 1628
1614 CHECK_LIST (list); 1629 CHECK_LIST (list);
1615 1630
1616 if (NILP (n)) 1631 if (!NILP (n))
1617 int_n = 1;
1618 else
1619 { 1632 {
1620 CHECK_NATNUM (n); 1633 CHECK_NATNUM (n);
1621 int_n = XINT (n); 1634 int_n = XINT (n);
1622 } 1635 }
1623 1636
1624 { 1637 if (CONSP (list))
1625 Lisp_Object retval = Qnil; 1638 {
1626 Lisp_Object tail = list; 1639 Lisp_Object tail = list;
1627 1640
1628 EXTERNAL_LIST_LOOP_1 (list) 1641 EXTERNAL_LIST_LOOP_3 (elt, list, list_tail)
1629 { 1642 {
1630 if (--int_n < 0) 1643 if (--int_n < 0)
1631 { 1644 {
1632 retval = Fcons (XCAR (tail), retval); 1645 if (NILP (retval_tail))
1633 tail = XCDR (tail); 1646 {
1634 } 1647 retval = retval_tail = Fcons (XCAR (tail), Qnil);
1635 } 1648 }
1636 1649 else
1637 return Fnreverse (retval); 1650 {
1638 } 1651 XSETCDR (retval_tail, Fcons (XCAR (tail), Qnil));
1652 retval_tail = XCDR (retval_tail);
1653 }
1654
1655 tail = XCDR (tail);
1656 }
1657
1658 if (!CONSP (XCDR (list_tail)))
1659 {
1660 break;
1661 }
1662 }
1663 }
1664
1665 return retval;
1639 } 1666 }
1640 1667
1641 DEFUN ("member", Fmember, 2, 2, 0, /* 1668 DEFUN ("member", Fmember, 2, 2, 0, /*
1642 Return non-nil if ELT is an element of LIST. Comparison done with `equal'. 1669 Return non-nil if ELT is an element of LIST. Comparison done with `equal'.
1643 The value is actually the tail of LIST whose car is ELT. 1670 The value is actually the tail of LIST whose car is ELT.