improve writing infinite terms.

This commit is contained in:
Vítor Santos Costa 2010-11-01 20:10:32 +00:00
parent d1a0cfe21a
commit a44d847b61

View File

@ -546,15 +546,46 @@ from_pointer(CELL *ptr, struct rewind_term *rwt, struct write_globs *wglb)
while (IsVarTerm(*ptr) && !IsUnboundVar(ptr)) while (IsVarTerm(*ptr) && !IsUnboundVar(ptr))
ptr = (CELL *)*ptr; ptr = (CELL *)*ptr;
t = *ptr; t = *ptr;
if (!IsVarTerm(t)) { if (!IsVarTerm(t) && !IsAtomOrIntTerm(t)) {
struct rewind_term *x = rwt->parent;
if (wglb->keep_terms) { if (wglb->keep_terms) {
rwt->u.s.old = Yap_InitSlot(t); rwt->u.s.old = Yap_InitSlot(t);
rwt->u.s.ptr = Yap_InitSlot((CELL)ptr); rwt->u.s.ptr = Yap_InitSlot((CELL)ptr);
while (x) {
if (Yap_GetFromSlot(x->u.s.old) == t)
return TermFoundVar;
x = x->parent;
}
} else { } else {
rwt->u.d.old = t; rwt->u.d.old = t;
rwt->u.d.ptr = ptr; rwt->u.d.ptr = ptr;
while (x) {
if (x->u.d.old == t)
return TermFoundVar;
x = x->parent;
}
}
} else {
rwt->u.s.ptr = 0;
}
return t;
}
static Term
check_infinite_loop(Term t, struct rewind_term *x, struct write_globs *wglb)
{
if (wglb->keep_terms) {
while (x) {
if (Yap_GetFromSlot(x->u.s.old) == t)
return TermFoundVar;
x = x->parent;
}
} else {
while (x) {
if (x->u.d.old == t)
return TermFoundVar;
x = x->parent;
} }
*ptr = TermFoundVar;
} }
return t; return t;
} }
@ -573,7 +604,6 @@ restore_from_write(struct rewind_term *rwt, struct write_globs *wglb)
ptr = rwt->u.d.ptr; ptr = rwt->u.d.ptr;
t = rwt->u.d.old; t = rwt->u.d.old;
} }
*ptr = t;
} }
rwt->u.s.ptr = 0; rwt->u.s.ptr = 0;
} }
@ -604,35 +634,45 @@ write_list(Term t, int direction, int depth, struct write_globs *wglb, struct re
ti = TailOfTerm(t); ti = TailOfTerm(t);
if (IsVarTerm(ti)) if (IsVarTerm(ti))
break; break;
if (!IsPairTerm(ti)) if (!IsPairTerm(ti) ||
!IsPairTerm((ti = check_infinite_loop(ti, rwt, wglb))))
break; break;
ndirection = RepPair(ti)-RepPair(t); ndirection = RepPair(ti)-RepPair(t);
/* make sure we're not trapped in loops */ /* make sure we're not trapped in loops */
if (ndirection > 0) { if (ndirection > 0) {
do_jump = (direction < 0); do_jump = (direction <= 0);
} else if (ndirection == 0) { } else if (ndirection == 0) {
wrputc(',', wglb->writewch); wrputc(',', wglb->writewch);
putAtom(AtomFoundVar, wglb->Quote_illegal, wglb->writewch); putAtom(AtomFoundVar, wglb->Quote_illegal, wglb->writewch);
lastw = separator; lastw = separator;
return; return;
} else { } else {
do_jump = (direction > 0); do_jump = (direction >= 0);
} }
if (wglb->MaxDepth != 0 && depth > wglb->MaxDepth) { if (wglb->MaxDepth != 0 && depth > wglb->MaxDepth) {
wrputc('|', wglb->writewch); wrputc('|', wglb->writewch);
putAtom(Atom3Dots, wglb->Quote_illegal, wglb->writewch); putAtom(Atom3Dots, wglb->Quote_illegal, wglb->writewch);
return; return;
} }
wrputc(',', wglb->writewch);
lastw = separator; lastw = separator;
direction = ndirection; direction = ndirection;
depth++; depth++;
if (do_jump) if (do_jump)
break; break;
wrputc(',', wglb->writewch);
t = ti; t = ti;
} }
if (IsPairTerm(ti)) { if (IsPairTerm(ti)) {
write_list(from_pointer(RepPair(t)+1, &nrwt, wglb), direction, depth, wglb, &nrwt); Term nt = from_pointer(RepPair(t)+1, &nrwt, wglb);
/* we found an infinite loop */
if (IsAtomTerm(nt)) {
wrputc('|', wglb->writewch);
writeTerm(nt, 999, depth, FALSE, wglb, rwt);
} else {
/* keep going on the list */
wrputc(',', wglb->writewch);
write_list(nt, direction, depth, wglb, &nrwt);
}
restore_from_write(&nrwt, wglb); restore_from_write(&nrwt, wglb);
} else if (ti != MkAtomTerm(AtomNil)) { } else if (ti != MkAtomTerm(AtomNil)) {
wrputc('|', wglb->writewch); wrputc('|', wglb->writewch);
@ -685,11 +725,10 @@ writeTerm(Term t, int p, int depth, int rinfixarg, struct write_globs *wglb, str
if (yap_flags[WRITE_QUOTED_STRING_FLAG] && IsStringTerm(t)) { if (yap_flags[WRITE_QUOTED_STRING_FLAG] && IsStringTerm(t)) {
putString(t, wglb->writewch); putString(t, wglb->writewch);
} else { } else {
Term ls = t;
wrputc('[', wglb->writewch); wrputc('[', wglb->writewch);
lastw = separator; lastw = separator;
write_list(from_pointer(&ls, &nrwt, wglb), 0, depth, wglb, &nrwt); /* we assume t was already saved in the stack */
restore_from_write(&nrwt, wglb); write_list(t, 0, depth, wglb, rwt);
wrputc(']', wglb->writewch); wrputc(']', wglb->writewch);
lastw = separator; lastw = separator;
} }
@ -1033,8 +1072,6 @@ Yap_plwrite(Term t, int (*mywrite) (int, wchar_t), int flags, int priority)
{ {
struct write_globs wglb; struct write_globs wglb;
struct rewind_term rwt; struct rewind_term rwt;
rwt.parent = NULL;
rwt.u.s.ptr = 0;
wglb.writewch = mywrite; wglb.writewch = mywrite;
lastw = separator; lastw = separator;
@ -1046,6 +1083,8 @@ Yap_plwrite(Term t, int (*mywrite) (int, wchar_t), int flags, int priority)
/* notice: we must have ASP well set when using portray, otherwise /* notice: we must have ASP well set when using portray, otherwise
we cannot make recursive Prolog calls */ we cannot make recursive Prolog calls */
wglb.keep_terms = (flags & (Use_portray_f|To_heap_f)); wglb.keep_terms = (flags & (Use_portray_f|To_heap_f));
/* initialise wglb */
rwt.parent = NULL;
wglb.Ignore_ops = flags & Ignore_ops_f; wglb.Ignore_ops = flags & Ignore_ops_f;
/* protect slots for portray */ /* protect slots for portray */
writeTerm(from_pointer(&t, &rwt, &wglb), priority, 1, FALSE, &wglb, &rwt); writeTerm(from_pointer(&t, &rwt, &wglb), priority, 1, FALSE, &wglb, &rwt);