Fix bignum bugs with nth, elt, =
* src/bytecode.c (exec_byte_code): Support bignums when implementing nth, elt, and =. * src/lisp.h (SMALL_LIST_LEN_MAX): New constant. * src/fns.c (Fnthcdr): Use it. (Felt): Do not reject bignum indexes.
This commit is contained in:
parent
ad31afc35b
commit
81e7eef822
3 changed files with 20 additions and 29 deletions
|
@ -832,13 +832,14 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
CASE (Bnth):
|
||||
{
|
||||
Lisp_Object v2 = POP, v1 = TOP;
|
||||
CHECK_FIXNUM (v1);
|
||||
for (EMACS_INT n = XFIXNUM (v1); 0 < n && CONSP (v2); n--)
|
||||
if (RANGED_FIXNUMP (0, v1, SMALL_LIST_LEN_MAX))
|
||||
{
|
||||
v2 = XCDR (v2);
|
||||
rarely_quit (n);
|
||||
for (EMACS_INT n = XFIXNUM (v1); 0 < n && CONSP (v2); n--)
|
||||
v2 = XCDR (v2);
|
||||
TOP = CAR (v2);
|
||||
}
|
||||
TOP = CAR (v2);
|
||||
else
|
||||
TOP = Fnth (v1, v2);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
|
@ -985,15 +986,8 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
|
||||
CASE (Beqlsign):
|
||||
{
|
||||
Lisp_Object v2 = POP, v1 = TOP;
|
||||
if (FLOATP (v1) || FLOATP (v2))
|
||||
TOP = arithcompare (v1, v2, ARITH_EQUAL);
|
||||
else
|
||||
{
|
||||
CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (v1);
|
||||
CHECK_FIXNUM_OR_FLOAT_COERCE_MARKER (v2);
|
||||
TOP = EQ (v1, v2) ? Qt : Qnil;
|
||||
}
|
||||
Lisp_Object v1 = POP;
|
||||
TOP = arithcompare (TOP, v1, ARITH_EQUAL);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
|
@ -1264,23 +1258,16 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, Lisp_Object maxdepth,
|
|||
|
||||
CASE (Belt):
|
||||
{
|
||||
if (CONSP (TOP))
|
||||
Lisp_Object v2 = POP, v1 = TOP;
|
||||
if (CONSP (v1) && RANGED_FIXNUMP (0, v2, SMALL_LIST_LEN_MAX))
|
||||
{
|
||||
/* Exchange args and then do nth. */
|
||||
Lisp_Object v2 = POP, v1 = TOP;
|
||||
CHECK_FIXNUM (v2);
|
||||
/* Like the fast case for Bnth, but with args reversed. */
|
||||
for (EMACS_INT n = XFIXNUM (v2); 0 < n && CONSP (v1); n--)
|
||||
{
|
||||
v1 = XCDR (v1);
|
||||
rarely_quit (n);
|
||||
}
|
||||
v1 = XCDR (v1);
|
||||
TOP = CAR (v1);
|
||||
}
|
||||
else
|
||||
{
|
||||
Lisp_Object v1 = POP;
|
||||
TOP = Felt (TOP, v1);
|
||||
}
|
||||
TOP = Felt (v1, v2);
|
||||
NEXT;
|
||||
}
|
||||
|
||||
|
|
|
@ -1418,7 +1418,7 @@ DEFUN ("nthcdr", Fnthcdr, Snthcdr, 2, 2, 0,
|
|||
num = XFIXNUM (n);
|
||||
|
||||
/* Speed up small lists by omitting circularity and quit checking. */
|
||||
if (num < 128)
|
||||
if (num <= SMALL_LIST_LEN_MAX)
|
||||
{
|
||||
for (; 0 < num; num--, tail = XCDR (tail))
|
||||
if (! CONSP (tail))
|
||||
|
@ -1503,9 +1503,8 @@ N counts from zero. If LIST is not that long, nil is returned. */)
|
|||
|
||||
DEFUN ("elt", Felt, Selt, 2, 2, 0,
|
||||
doc: /* Return element of SEQUENCE at index N. */)
|
||||
(register Lisp_Object sequence, Lisp_Object n)
|
||||
(Lisp_Object sequence, Lisp_Object n)
|
||||
{
|
||||
CHECK_FIXNUM (n);
|
||||
if (CONSP (sequence) || NILP (sequence))
|
||||
return Fcar (Fnthcdr (n, sequence));
|
||||
|
||||
|
|
|
@ -4694,6 +4694,11 @@ enum
|
|||
Lisp_String)) \
|
||||
: make_unibyte_string (str, len))
|
||||
|
||||
/* The maximum length of "small" lists, as a heuristic. These lists
|
||||
are so short that code need not check for cycles or quits while
|
||||
traversing. */
|
||||
enum { SMALL_LIST_LEN_MAX = 127 };
|
||||
|
||||
/* Loop over conses of the list TAIL, signaling if a cycle is found,
|
||||
and possibly quitting after each loop iteration. In the loop body,
|
||||
set TAIL to the current cons. If the loop exits normally,
|
||||
|
|
Loading…
Add table
Reference in a new issue