]> git.eshelyaron.com Git - emacs.git/commitdiff
Move proper-list-p to C
authorPaul Eggert <eggert@cs.ucla.edu>
Tue, 24 Jul 2018 22:58:46 +0000 (15:58 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Tue, 24 Jul 2018 23:08:09 +0000 (16:08 -0700)
Since C code can use it and it’s simple, we might as well use C.
* lisp/subr.el (proper-list-p): Move to C code.
* src/eval.c (signal_error): Simplify by using Fproper_list_p.
* src/fns.c (Fproper_list_p): New function, moved here from Lisp.

Simplify signal_error
* src/eval.c (signal_error): Simplify by using FOR_EACH_TAIL_SAFE.

lisp/subr.el
src/eval.c
src/fns.c
src/lisp.h

index 10343e69db8e017ffcfa717b92ac5a2f90f83846..6b30371a868335933a6b1c526ceef4c4ea290fd9 100644 (file)
@@ -555,12 +555,6 @@ If N is omitted or nil, remove the last element."
           (if (> n 0) (setcdr (nthcdr (- (1- m) n) list) nil))
           list))))
 
-(defun proper-list-p (object)
-  "Return OBJECT's length if it is a proper list, nil otherwise.
-A proper list is neither circular nor dotted (i.e., its last cdr
-is nil)."
-  (and (listp object) (ignore-errors (length object))))
-
 (defun delete-dups (list)
   "Destructively remove `equal' duplicates from LIST.
 Store the result in LIST and return it.  LIST must be a proper list.
index 256ca8ffdc8904d7cd6f61af62e5794d59f673c6..5964dd1867a9d7fd31c2b819f1489c5a1bdac4a5 100644 (file)
@@ -1732,28 +1732,12 @@ xsignal3 (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2, Lisp_Obj
 }
 
 /* Signal `error' with message S, and additional arg ARG.
-   If ARG is not a genuine list, make it a one-element list.  */
+   If ARG is not a proper list, make it a one-element list.  */
 
 void
 signal_error (const char *s, Lisp_Object arg)
 {
-  Lisp_Object tortoise, hare;
-
-  hare = tortoise = arg;
-  while (CONSP (hare))
-    {
-      hare = XCDR (hare);
-      if (!CONSP (hare))
-       break;
-
-      hare = XCDR (hare);
-      tortoise = XCDR (tortoise);
-
-      if (EQ (hare, tortoise))
-       break;
-    }
-
-  if (!NILP (hare))
+  if (NILP (Fproper_list_p (arg)))
     arg = list1 (arg);
 
   xsignal (Qerror, Fcons (build_string (s), arg));
index e7424c34718405ebb6319cf86dd5d60c616fc243..5247140ead46db8cef2e9d3534e1a93955cbf2cf 100644 (file)
--- a/src/fns.c
+++ b/src/fns.c
@@ -144,6 +144,28 @@ which is at least the number of distinct elements.  */)
   return make_fixnum_or_float (len);
 }
 
+DEFUN ("proper-list-p", Fproper_list_p, Sproper_list_p, 1, 1, 0,
+       doc: /* Return OBJECT's length if it is a proper list, nil otherwise.
+A proper list is neither circular nor dotted (i.e., its last cdr is nil).  */
+       attributes: const)
+  (Lisp_Object object)
+{
+  intptr_t len = 0;
+  Lisp_Object last_tail = object;
+  Lisp_Object tail = object;
+  FOR_EACH_TAIL_SAFE (tail)
+    {
+      len++;
+      rarely_quit (len);
+      last_tail = XCDR (tail);
+    }
+  if (!NILP (last_tail))
+    return Qnil;
+  if (MOST_POSITIVE_FIXNUM < len)
+    xsignal0 (Qoverflow_error);
+  return make_number (len);
+}
+
 DEFUN ("string-bytes", Fstring_bytes, Sstring_bytes, 1, 1, 0,
        doc: /* Return the number of bytes in STRING.
 If STRING is multibyte, this may be greater than the length of STRING.  */)
@@ -5295,6 +5317,7 @@ this variable.  */);
   defsubr (&Srandom);
   defsubr (&Slength);
   defsubr (&Ssafe_length);
+  defsubr (&Sproper_list_p);
   defsubr (&Sstring_bytes);
   defsubr (&Sstring_distance);
   defsubr (&Sstring_equal);
index 8ddd363d2dd7442ee4a4ce148f7d8ce29ee7b9ab..96de60e4670df4da913275422759245ef62f7ed3 100644 (file)
@@ -4699,7 +4699,7 @@ enum
 #define FOR_EACH_TAIL(tail) \
   FOR_EACH_TAIL_INTERNAL (tail, circular_list (tail), true)
 
-/* Like FOR_EACH_TAIL (LIST), except do not signal or quit.
+/* Like FOR_EACH_TAIL (TAIL), except do not signal or quit.
    If the loop exits due to a cycle, TAIL’s value is undefined.  */
 
 #define FOR_EACH_TAIL_SAFE(tail) \