aboutsummaryrefslogtreecommitdiffstats
path: root/src/lisp.h
diff options
context:
space:
mode:
authorPaul Eggert2017-02-05 13:25:37 -0800
committerPaul Eggert2017-02-05 13:30:28 -0800
commitb7fa6b1f1cee9d1b71553fa665843774d2e5cf3d (patch)
tree3a6df68a8377005aec8872de00df48b2cbf9f714 /src/lisp.h
parent5e222f673717718cd0ee209487cc06637bd142fc (diff)
downloademacs-b7fa6b1f1cee9d1b71553fa665843774d2e5cf3d.tar.gz
emacs-b7fa6b1f1cee9d1b71553fa665843774d2e5cf3d.zip
Simplify use of FOR_EACH_TAIL
* src/data.c (circular_list): New function. * src/lisp.h (FOR_EACH_TAIL): Use Brent’s algorithm and C99 for-loop decl, to eliminate the need for the args TAIL, TORTOISE and N, and to speed things up a bit on typical hosts with optimization. All uses changed (Bug#25605).
Diffstat (limited to 'src/lisp.h')
-rw-r--r--src/lisp.h34
1 files changed, 20 insertions, 14 deletions
diff --git a/src/lisp.h b/src/lisp.h
index a9011b4a8be..102e8bd70ef 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3317,6 +3317,7 @@ extern struct Lisp_Symbol *indirect_variable (struct Lisp_Symbol *);
3317extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object); 3317extern _Noreturn void args_out_of_range (Lisp_Object, Lisp_Object);
3318extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object, 3318extern _Noreturn void args_out_of_range_3 (Lisp_Object, Lisp_Object,
3319 Lisp_Object); 3319 Lisp_Object);
3320extern _Noreturn void circular_list (Lisp_Object);
3320extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *); 3321extern Lisp_Object do_symval_forwarding (union Lisp_Fwd *);
3321enum Set_Internal_Bind { 3322enum Set_Internal_Bind {
3322 SET_INTERNAL_SET, 3323 SET_INTERNAL_SET,
@@ -4585,20 +4586,25 @@ enum
4585 Lisp_String)) \ 4586 Lisp_String)) \
4586 : make_unibyte_string (str, len)) 4587 : make_unibyte_string (str, len))
4587 4588
4588/* Loop over all tails of a list, checking for cycles. 4589/* Loop over tails of LIST, checking for dotted lists and cycles.
4589 FIXME: Make tortoise and n internal declarations. 4590 In the loop body, ‘li.tail’ is the current cons; the name ‘li’ is
4590 FIXME: Unroll the loop body so we don't need `n'. */ 4591 short for “list iterator”. The expression LIST may be evaluated
4591#define FOR_EACH_TAIL(hare, list, tortoise, n) \ 4592 more than once, and so should not have side effects. The loop body
4592 for ((tortoise) = (hare) = (list), (n) = true; \ 4593 should not modify the list’s top level structure other than by
4593 CONSP (hare); \ 4594 perhaps deleting the current cons.
4594 (hare = XCDR (hare), (n) = !(n), \ 4595
4595 ((n) \ 4596 Use Brent’s teleporting tortoise-hare algorithm. See:
4596 ? (EQ (hare, tortoise) \ 4597 Brent RP. BIT. 1980;20(2):176-84. doi:10.1007/BF01933190
4597 ? xsignal1 (Qcircular_list, list) \ 4598 http://maths-people.anu.edu.au/~brent/pd/rpb051i.pdf */
4598 : (void) 0) \ 4599
4599 /* Move tortoise before the next iteration, in case */ \ 4600#define FOR_EACH_TAIL(list) \
4600 /* the next iteration does an Fsetcdr. */ \ 4601 for (struct { Lisp_Object tail, tortoise; intptr_t n, max; } li \
4601 : (void) ((tortoise) = XCDR (tortoise))))) 4602 = { list, list, 2, 2 }; \
4603 CONSP (li.tail) || (CHECK_LIST_END (li.tail, list), false); \
4604 (li.tail = XCDR (li.tail), \
4605 (li.n-- == 0 \
4606 ? (void) (li.n = li.max <<= 1, li.tortoise = li.tail) \
4607 : EQ (li.tail, li.tortoise) ? circular_list (list) : (void) 0)))
4602 4608
4603/* Do a `for' loop over alist values. */ 4609/* Do a `for' loop over alist values. */
4604 4610