refactor pic_list_p

This commit is contained in:
Yuichi Nishiwaki 2014-03-16 22:51:33 +09:00
parent 6cc6046ea3
commit 27d4853aef
1 changed files with 19 additions and 13 deletions

View File

@ -48,27 +48,33 @@ pic_cdr(pic_state *pic, pic_value obj)
bool bool
pic_list_p(pic_state *pic, pic_value obj) pic_list_p(pic_state *pic, pic_value obj)
{ {
UNUSED(pic); pic_value local, rapid;
pic_value twice=obj; int i;
/* This code checks whether obj is a circular list UNUSED(pic);
using Floyd's cycle-finding algorithm. */
while ( 1 ) { /* loops until a cycle is detected or an object other than a pair is found */ /* Floyd's cycle-finding algorithm. */
int i;
local = rapid = obj;
while (true) {
/* advance rapid fast-forward; runs 2x faster than local */
for (i = 0; i < 2; ++i) { for (i = 0; i < 2; ++i) {
if (pic_pair_p(twice)) { if (pic_pair_p(rapid)) {
twice = pic_pair_ptr(twice)->cdr; rapid = pic_pair_ptr(rapid)->cdr;
} }
else { else {
return pic_nil_p(twice); return pic_nil_p(rapid);
} }
} }
obj = pic_pair_ptr(obj)->cdr; /* Since obj progresses slower than twice, it is guaranteed that obj is a pair. */
if (pic_eq_p(obj,twice)) { /* obj is a circular list */ /* advance local */
local = pic_pair_ptr(local)->cdr;
if (pic_eq_p(local, rapid)) {
return false; return false;
} }
} }
/* unreachable */
} }
pic_value pic_value