diff --git a/C/terms.c b/C/terms.c index 6c55cb21f..6d20c3b0f 100644 --- a/C/terms.c +++ b/C/terms.c @@ -133,7 +133,7 @@ typedef struct { typedef struct non_single_struct_t { CELL *ptd0; CELL d0; - CELL *pt0, *pt0_end; + CELL *pt0, *pt0_end, *ptf; } non_singletons_t; #define WALK_COMPLEX_TERM__(LIST0, STRUCT0, PRIMI0) \ @@ -224,11 +224,11 @@ typedef struct non_single_struct_t { #define def_trail_overflow() \ trail_overflow : { \ - pop_text_stack(lvl); \ LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL; \ LOCAL_Error_Size = (TR - TR0) * sizeof(tr_fr_ptr *); \ clean_tr(TR0 PASS_REGS); \ HR = InitialH; \ + pop_text_stack(lvl); \ return 0L; \ } @@ -760,7 +760,6 @@ static Term new_vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, TrailTerm(TR++) = t; if ((tr_fr_ptr)LOCAL_TrailTop - TR < 1024) { if (!Yap_growtrail((TR - TR0) * sizeof(tr_fr_ptr *), true)) { - pop_text_stack(lvl); goto trail_overflow; } } @@ -812,7 +811,7 @@ static Term new_vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, HR[-1] = TermNil; return output; } else { - return TermNil; + return 0; } def_aux_overflow(); @@ -1349,7 +1348,8 @@ static Term UNFOLD_LOOP(Term t, Term *b, Term l) { return o; } -static int loops_in_complex_term(CELL *pt0, CELL *pt0_end, Term *listp, +static int loops_in_complex_term(CELL *pt0, CELL *pt0_end, + Term *listp, Term tail USES_REGS) { int lvl = push_text_stack(); @@ -1360,6 +1360,7 @@ static int loops_in_complex_term(CELL *pt0, CELL *pt0_end, Term *listp, to_visit0 = to_visit; to_visit_max = to_visit0 + 1024; + CELL *ptf = HR-1; restart: while (pt0 < pt0_end) { CELL d0; @@ -1375,7 +1376,6 @@ restart: goto aux_overflow; } CELL *headp = RepPair(d0); - d0 = headp[0]; if (IsAtomTerm(d0) && (CELL *)AtomOfTerm(d0) >= (CELL *)to_visit0 && (CELL *)AtomOfTerm(d0) < (CELL *)to_visit_max) { @@ -1383,22 +1383,26 @@ restart: struct non_single_struct_t *v0 = (struct non_single_struct_t *)AtomOfTerm(d0); if (listp) { - *ptd0 = UNFOLD_LOOP(AbsPair(headp), listp, tail); + *ptf = UNFOLD_LOOP(AbsPair(v0->ptf-1), listp, tail); + ptf++; } else { - *ptd0 = BREAK_LOOP(to_visit - v0); + *ptf++ = BREAK_LOOP(to_visit - v0); } - - goto restart; + continue; } + *ptf++ = AbsPair(HR); to_visit->pt0 = pt0; to_visit->pt0_end = pt0_end; to_visit->ptd0 = headp; + to_visit->ptf = ptf; to_visit->d0 = d0; *headp = MkAtomTerm((AtomEntry *)to_visit); to_visit++; pt0 = headp; pt0_end = pt0 + 1; ptd0 = pt0; + ptf = HR; + HR+=2; goto list_loop; } else if (IsApplTerm(d0)) { register Functor f; @@ -1406,35 +1410,44 @@ restart: /* store the terms to visit */ ap2 = RepAppl(d0); f = (Functor)(*ap2); - if (IsExtensionFunctor(f)) + if (IsExtensionFunctor(f)) { + *ptf++ = d0; continue; + } if (IsAtomTerm((CELL)f)) { - + struct non_single_struct_t *v0 = (struct non_single_struct_t *)AtomOfTerm(*ap2); if (listp) { - *ptd0 = UNFOLD_LOOP(AbsAppl(ap2), listp, tail); + *ptf = UNFOLD_LOOP(AbsAppl(v0->ptf-1), listp, tail); + ptf++; } else { - *ptd0 = BREAK_LOOP(to_visit - - (struct non_single_struct_t *)AtomOfTerm(*ap2)); + *ptf++ = BREAK_LOOP(to_visit - v0); } - goto restart; + continue; } // STRUCT0; if (to_visit + 32 >= to_visit_max) { goto aux_overflow; } + *ptf++ = AbsAppl(HR); + HR[0] = (CELL)f; to_visit->pt0 = pt0; to_visit->pt0_end = pt0_end; to_visit->ptd0 = ap2; to_visit->d0 = *ap2; + to_visit->ptf = ptf; *ap2 = MkAtomTerm((AtomEntry *)to_visit); to_visit++; pt0 = ap2; pt0_end = ap2 + (ArityOfFunctor(f)); + ptf = HR+1; + HR = ptf +ArityOfFunctor(f); + } else { + *ptf++ = d0; } goto restart; derefa_body(d0, ptd0, vars_in_term_unk, vars_in_term_nvar); - + *ptf++ = d0; goto restart; } /* Do we still have compound terms to visit */ @@ -1442,10 +1455,10 @@ restart: to_visit--; pt0 = to_visit->pt0; + ptf = to_visit->ptf; pt0_end = to_visit->pt0_end; CELL *ptd0 = to_visit->ptd0; - if (!IsVarTerm(*ptd0)) - *ptd0 = to_visit->d0; + *ptd0 = to_visit->d0; goto restart; } @@ -1461,11 +1474,15 @@ Term Yap_BreakCycles(Term inp, UInt arity, Term *listp, Term tail USES_REGS) { return t; } else { Int res; - + CELL *op = HR; + HR++; res = loops_in_complex_term((&t) - 1, &t, listp, tail PASS_REGS); if (res < 0) return -1; - return t; + if (IsPairTerm(t)) + return AbsPair(op); + else + return AbsAppl(op); } } @@ -1481,7 +1498,7 @@ Term Yap_BreakCycles(Term inp, UInt arity, Term *listp, Term tail USES_REGS) { */ static Int p_break_rational(USES_REGS1) { - Term t = Yap_CopyTerm(Deref(ARG1)); + Term t = (ARG1); Term l = Deref(ARG4), k; if (IsVarTerm(l)) Yap_unify(l, MkVarTerm()); diff --git a/C/utilpreds.c b/C/utilpreds.c index 6da178022..092ea2ced 100644 --- a/C/utilpreds.c +++ b/C/utilpreds.c @@ -590,433 +590,6 @@ add_to_list( Term inp, Term v, Term t PASS_REGS) } -static int -break_rationals_complex_term(CELL *pt0, CELL *pt0_end, CELL *ptf, Term *vout, Term vin,CELL *HLow USES_REGS) -{ - - struct bp_frame *to_visit0, *to_visit = (struct bp_frame *)Yap_PreAllocCodeSpace() ; - CELL *HB0 = HB; - tr_fr_ptr TR0 = TR; - - HB = HR; - to_visit0 = to_visit; - loop: - while (pt0 < pt0_end) { - register CELL d0; - register CELL *ptd0; - ++ pt0; - ptd0 = pt0; - d0 = *ptd0; - deref_head(d0, copy_term_unk); - copy_term_nvar: - { - if (IsPairTerm(d0)) { - CELL *headp = RepPair(d0); - //fprintf(stderr, "%d \n", RepPair(headp[0])- ptf); - if (IsVarTerm(headp[0]) && IN_BETWEEN(HB, (headp[0]),HR)) { - Term v = MkVarTerm(); - *ptf = v; - vin = add_to_list(vin, (CELL)(ptf), AbsPair(ptf) ); - ptf++; - continue; - } - if (to_visit+1 >= (struct bp_frame *)AuxSp) { - goto heap_overflow; - } - *ptf++ = (CELL)(HR); - to_visit->start_cp = pt0; - to_visit->end_cp = pt0_end; - to_visit->to = ptf; - to_visit->oldp = headp; - d0 = to_visit->oldv = headp[0]; - /* fool the system into thinking we had a variable there */ - to_visit ++; - pt0 = headp; - pt0_end = headp + 1; - ptf = HR; - *headp = AbsPair(HR); - HR += 2; - if (HR > ASP - 2048) { - goto overflow; - } - if (IsVarTerm(d0) && d0 == (CELL)headp) { - RESET_VARIABLE(ptf); - ptf++; - continue; - } - d0 = Deref(d0); - if (!IsVarTerm(d0)) { - goto copy_term_nvar; - } else { - *ptf++ = d0; - } - continue; - } else if (IsApplTerm(d0)) { - register Functor f; - register CELL *headp; - /* store the terms to visit */ - headp = RepAppl(d0)+1; - f = (Functor)(headp[-1]); - if (IsExtensionFunctor(f)) { - *ptf++ = d0; /* you can just copy other extensions. */ - continue; - } - if (IsApplTerm(headp[0]) && IN_BETWEEN(HB, RepAppl(headp[0]),HR)) { - RESET_VARIABLE(ptf); - vin = add_to_list(vin, (CELL)ptf, headp[0] ); - ptf++; - continue; - } - - arity_t arity = ArityOfFunctor(f); - if (to_visit+1 >= (struct bp_frame *)AuxSp) { - goto heap_overflow; - } - *ptf++ = AbsAppl(HR); - to_visit->start_cp = pt0; - to_visit->end_cp = pt0_end; - to_visit->to = ptf; - to_visit->oldp = headp; - d0 = to_visit->oldv = headp[0]; - /* fool the system into thinking we had a variable there */ - to_visit ++; - pt0 = headp; - pt0_end = headp + (arity-1); - ptf = HR; - if (HR > ASP - 2048) { - goto overflow; - } - *ptf++ =(CELL)f; - *headp = AbsAppl(HR); - HR += (arity+1); - d0 = Deref(d0); - if (!IsVarTerm(d0)) { - goto copy_term_nvar; - } else { - *ptf++ = d0; - } - continue; - } else { - /* just copy atoms or integers */ - *ptf++ = d0; - } - continue; - } - - derefa_body(d0, ptd0, copy_term_unk, copy_term_nvar); - *ptf++ = (CELL) ptd0; - } - /* Do we still have compound terms to visit */ - if (to_visit > to_visit0) { - to_visit --; - *to_visit->oldp = to_visit->oldv; - ptf = to_visit->to; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - goto loop; - } - - /* restore our nice, friendly, term to its original state */ - HB = HB0; - *vout = vin; - return true; - - overflow: - /* oops, we're in trouble */ - HR = HLow; - /* we've done it */ - /* restore our nice, friendly, term to its original state */ - HB = HB0; -#ifdef RATIONAL_TREES - while (to_visit > to_visit0) { - to_visit --; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - ptf = to_visit->to; - *to_visit->oldp = to_visit->oldv; - } -#endif - reset_trail(TR0); - /* follow chain of multi-assigned variables */ - return -1; - - heap_overflow: - /* oops, we're in trouble */ - HR = HLow; - /* we've done it */ - /* restore our nice, friendly, term to its original state */ - HB = HB0; -#ifdef RATIONAL_TREES - while (to_visit > to_visit0) { - to_visit --; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - ptf = to_visit->to; - *to_visit->oldp = to_visit->oldv; - } -#endif - reset_trail(TR0); - LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)to_visit0; - return -3; -} - - -Term -Yap_BreakRational(Term inp, UInt arity, Term *to, Term ti USES_REGS) { - Term t = Deref(inp); - Term tii = ti; - tr_fr_ptr TR0 = TR; - - if (IsVarTerm(t)) { - *to = ti; - return t; - } else if (IsPrimitiveTerm(t)) { - *to = ti; - return t; - } else if (IsPairTerm(t)) { - CELL *ap; - CELL *Hi; - - restart_list: - ap = RepPair(t); - Hi = HR; - HR += 2; - { - Int res; - if ((res = break_rationals_complex_term(ap-1, ap+1, Hi, to, ti, Hi PASS_REGS)) < 0) { - HR = Hi; - if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L) - return FALSE; - goto restart_list; - } else if (*to == tii) { - HR = Hi; - return t; - } else { - return AbsPair(Hi); - } - } - } else { - Functor f; - CELL *HB0; - CELL *ap; - - restart_appl: - f = FunctorOfTerm(t); - if (IsExtensionFunctor(f)) { - *to = ti; - return t; - } - HB0 = HR; - ap = RepAppl(t); - HR[0] = (CELL)f; - arity = ArityOfFunctor(f); - HR += 1+arity; - - { - Int res; - if ((res = break_rationals_complex_term(ap, ap+(arity), HB0+1, to, ti, HB0 PASS_REGS)) < 0) { - HR = HB0; - if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L) - return FALSE; - goto restart_appl; - } else if (*to == ti) { - HR = HB0; - return t; - } else { - return AbsAppl(HB0); - } - } - } -} - -static int -break_complex_term(CELL *pt0, CELL *pt0_end, CELL *ptf, Term *of, Term oi, CELL *HLow USES_REGS) -{ - - struct copy_frame *to_visit0, *to_visit = (struct copy_frame *)Yap_PreAllocCodeSpace(); - CELL *HB0 = HB; - tr_fr_ptr TR0 = TR; - CELL new = 0L; - - HB = HLow; - to_visit0 = to_visit; - loop: - while (pt0 < pt0_end) { - register CELL d0; - register CELL *ptd0; - ++ pt0; - ptd0 = pt0; - d0 = *ptd0; - if (new) { - /* mark cell as pointing to new copy */ - /* we can only mark after reading the value of the first argument */ - TrailedMaBind(pt0, new); - new = 0L; - } - deref_head(d0, break_rationals_unk); - break_rationals_nvar: - { - CELL first; - CELL *newp; - if (IsPairTerm(d0)) { - CELL *ap2 = RepPair(d0); - - if (IsVarTerm(first = *ap2) && (newp = (CELL*)first) && newp >= HB && newp < HR) { - // found a marked term: - found_term: - if (!IsVarTerm(*newp)) { - Term v = (CELL)newp, t = *newp; - RESET_VARIABLE(newp); - oi = add_to_list( oi, v, t PASS_REGS); - } - *ptf++ = (CELL)newp; - continue; - } - new = (CELL)ptf; - *ptf++ = AbsPair(HR); - if (pt0 < pt0_end) { - if (to_visit+1 >= (struct copy_frame *)AuxSp) { - goto heap_overflow; - } - to_visit->start_cp = pt0; - to_visit->end_cp = pt0_end; - to_visit->to = ptf; - to_visit ++; - } - pt0 = ap2 - 1; - pt0_end = ap2 + 1; - ptf = HR; - HR += 2; - if (HR > ASP - 2048) { - goto overflow; - } - } else if (IsApplTerm(d0)) { - register Functor f; - register CELL *ap2; - /* store the terms to visit */ - ap2 = RepAppl(d0); - f = (Functor)(*ap2); - if (IsExtensionFunctor(f)) { - *ptf++ = d0; /* you can just share extensions, what about DB? */ - continue; - } - if (IsVarTerm(first = ap2[1]) && (newp = (CELL*)first) && newp >= HB && newp < HR) { - goto found_term; - } - // new - /* store the terms to visit */ - new = (CELL)ptf; - *ptf++ = AbsAppl(HR); - if (pt0 < pt0_end) { - if (to_visit+1 >= (struct copy_frame *)AuxSp) { - goto heap_overflow; - } - to_visit->start_cp = pt0; - to_visit->end_cp = pt0_end; - to_visit->to = ptf; - to_visit ++; - } - d0 = ArityOfFunctor(f); - pt0 = ap2; - pt0_end = ap2 + d0; - /* store the functor for the new term */ - HR[0] = (CELL)f; - ptf = HR+1; - HR += 1+d0; - if (HR > ASP - 2048) { - goto overflow; - } - } else { - /* just copy atoms or integers */ - *ptf++ = d0; - } - continue; - } - - derefa_body(d0, ptd0, break_rationals_unk, break_rationals_nvar); - *ptf++ = d0; - } - /* Do we still have compound terms to visit */ - if (to_visit > to_visit0) { - to_visit --; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - ptf = to_visit->to; - goto loop; - } - - /* restore our nice, friendly, term to its original state */ - HB = HB0; - reset_trail(TR0); - *of = oi; - return TRUE; - - overflow: - /* oops, we're in trouble */ - HR = HLow; - /* we've done it */ - /* restore our nice, friendly, term to its original state */ - HB = HB0; - while (to_visit > to_visit0) { - to_visit --; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - ptf = to_visit->to; - } - reset_trail(TR0); - /* follow chain of multi-assigned variables */ - return -1; - - heap_overflow: - /* oops, we're in trouble */ - HR = HLow; - /* we've done it */ - /* restore our nice, friendly, term to its original state */ - HB = HB0; - while (to_visit > to_visit0) { - to_visit --; - pt0 = to_visit->start_cp; - pt0_end = to_visit->end_cp; - ptf = to_visit->to; - } - reset_trail(TR0); - LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)to_visit0; - return -3; -} - -Term -Yap_BreakTerm(Term inp, UInt arity, Term *to, Term ti USES_REGS) { - Term t = Deref(inp); - tr_fr_ptr TR0 = TR; - - if (IsVarTerm(t)) { - *to = ti; - return t; - } else if (IsPrimitiveTerm(t)) { - *to = ti; - return t; - } else { - CELL *ap; - CELL *Hi = HR; - - restart_term: - ap = &t; - Hi = HR++; - { - int res; - - if ((res = break_complex_term(ap-1, ap, Hi, to, ti, Hi PASS_REGS)) < 0) { - HR = Hi; - if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L) - return FALSE; - goto restart_term; - } - } - return Hi[0]; - } -} - - /* FAST EXPORT ROUTINE. Export a Prolog term to something like: diff --git a/C/write.c b/C/write.c index 3da73070b..edd6a0717 100644 --- a/C/write.c +++ b/C/write.c @@ -1084,16 +1084,16 @@ void Yap_plwrite(Term t, StreamDesc *mywrite, int max_depth, int flags, yhandle_t lvl = push_text_stack(); struct write_globs wglb; struct rewind_term rwt; + t = Deref(t); rwt.parent = NULL; wglb.stream = mywrite; wglb.Ignore_ops = flags & Ignore_ops_f; wglb.Write_strings = flags & BackQuote_String_f; - if (!(flags & Ignore_cyclics_f) && Yap_IsCyclicTerm(t)) { - writeTerm(Yap_BreakCycles(t, 1, NULL, TermNil PASS_REGS), priority, 1, false, &wglb, &rwt); - } else { - /* protect slots for portray */ - writeTerm(t, priority, 1, false, &wglb, &rwt); + if ((flags & Handle_cyclics_f) && Yap_IsCyclicTerm(t) ){ + t = Yap_BreakCycles(t, 3, NULL, TermNil PASS_REGS); } + /* protect slots for portray */ + writeTerm(t, priority, 1, false, &wglb, &rwt); if (flags & New_Line_f) { if (flags & Fullstop_f) { wrputc('.', wglb.stream); diff --git a/include/YapStreams.h b/include/YapStreams.h index 4eff718b6..2d69fc1a8 100644 --- a/include/YapStreams.h +++ b/include/YapStreams.h @@ -194,7 +194,7 @@ typedef enum { /* we accept two domains for the moment, IPV6 may follow */ #define Handle_vars_f 0x04 #define Use_portray_f 0x08 #define To_heap_f 0x10 -#define Ignore_cyclics_f 0x20 +#define Handle_cyclics_f 0x20 #define Use_SWI_Stream_f 0x40 #define BackQuote_String_f 0x80 #define AttVar_None_f 0x100 diff --git a/os/writeterm.c b/os/writeterm.c index b55b96c63..ce96bf572 100644 --- a/os/writeterm.c +++ b/os/writeterm.c @@ -231,8 +231,9 @@ static bool write_term(int output_stream, Term t, xarg *args USES_REGS) { goto end; } } - if (args[WRITE_CYCLES].used && args[WRITE_CYCLES].tvalue == TermFalse) { - flags |= Ignore_cyclics_f; + if (!args[WRITE_CYCLES].used || (args[WRITE_CYCLES].used + && args[WRITE_CYCLES].tvalue == TermTrue)) { + flags |= Handle_cyclics_f; } if (args[WRITE_QUOTED].used && args[WRITE_QUOTED].tvalue == TermTrue) { flags |= Quote_illegal_f; diff --git a/regression/cyclics.yap b/regression/cyclics.yap index 800d66d4c..4c2ba4d59 100644 --- a/regression/cyclics.yap +++ b/regression/cyclics.yap @@ -14,6 +14,11 @@ main :- fail. main :- main( writeln(X), X). +main :- + writeln('-----------------------'), + fail. +main :- + main((rational_term_to_tree(X,A,B,[]),writeln(A:B)), X). main. main(G, X) :-