YAP 7.1.0
utilpreds.c
Go to the documentation of this file.
1/*************************************************************************
2* *
3* YAP Prolog *
4* *
5* Yap Prolog was developed at NCCUP - Universidade do Porto *
6* *
7* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
8* *
9**************************************************************************
10* *
11* File: utilpreds.c *
12* Last rev: 4/03/88 *
13* mods: *
14* comments: new utility predicates for YAP *
15* *
16*************************************************************************/
17#ifdef SCCS
18static char SccsId[] = "@(#)utilpreds.c 1.3";
19#endif
29#include "absmi.h"
30#include "YapHeap.h"
31#include "yapio.h"
32#include "attvar.h"
33#ifdef HAVE_STRING_H
34#include "string.h"
35#endif
36
37#include "terms.h"
38
39typedef struct {
40 Term old_var;
41 Term new_var;
42} *vcell;
43
44
45static CELL vars_in_complex_term(CELL *, CELL *, Term CACHE_TYPE);
46static Int p_non_singletons_in_term( USES_REGS1);
47static CELL non_singletons_in_complex_term(CELL *, CELL * CACHE_TYPE);
48static Int p_variables_in_term( USES_REGS1 );
49static Int p_ground( USES_REGS1 );
50
51#ifdef DEBUG
52static Int p_force_trail_expansion( USES_REGS1 );
53#endif /* DEBUG */
54
55static inline void
56clean_dirty_tr(tr_fr_ptr TR0 USES_REGS) {
57 if (TR != TR0) {
58 tr_fr_ptr pt = TR0;
59
60 do {
61 Term p = TrailTerm(pt++);
62 RESET_VARIABLE(p);
63 } while (pt != TR);
64 TR = TR0;
65 }
66}
67
68
69static Term
70handle_cp_overflow(int res, tr_fr_ptr TR0, UInt arity, Term t)
71{
72 CACHE_REGS
73 XREGS[arity+1] = t;
74 switch(res) {
75 case -1:
76 if (!Yap_dogc(PASS_REGS1)) {
77 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
78 return 0L;
79 }
80 return Deref(XREGS[arity+1]);
81 case -2:
82 return Deref(XREGS[arity+1]);
83 case -3:
84 {
85 UInt size = LOCAL_Error_Size;
86 LOCAL_Error_Size = 0L;
87 if (size > 4*1024*1024)
88 size = 4*1024*1024;
89 if (!Yap_ExpandPreAllocCodeSpace(size, NULL, TRUE)) {
90 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, TermNil, LOCAL_ErrorMessage);
91 return 0L;
92 }
93 }
94 return Deref(XREGS[arity+1]);
95 case -4:
96 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), FALSE)) {
97 Yap_ThrowError(RESOURCE_ERROR_TRAIL, TermNil, LOCAL_ErrorMessage);
98 return 0L;
99 }
100 return Deref(XREGS[arity+1]);
101 default:
102 return 0L;
103 }
104}
105
106#if 0
107static int
108copy_complex_term(CELL *pt0, CELL *pt0_end, int share, int newattvs, CELL *ptf, CELL *HLow USES_REGS)
109{
110
111 struct cp_frame *tovisit0, *tovisit = (struct cp_frame *)Yap_PreAllocCodeSpace();
112 CELL *HB0 = HB;
113 tr_fr_ptr TR0 = TR;
114 int ground = TRUE;
115
116 HB = HLow;
117 tovisit0 = tovisit;
118 loop:
119 while (pt0 < pt0_end) {
120 register CELL d0;
121 register CELL *ptd0;
122 ++ pt0;
123 ptd0 = pt0;
124 d0 = *ptd0;
125 deref_head(d0, copy_term_unk);
126 copy_term_nvar:
127 {
128 if (IsPairTerm(d0)) {
129 CELL *ap2 = RepPair(d0);
130 if (ap2 >= HB && ap2 < HR) {
131 /* If this is newer than the current term, just reuse */
132 *ptf++ = d0;
133 continue;
134 }
135 *ptf = AbsPair(HR);
136 ptf++;
137#ifdef RATIONAL_TREES
138 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
139 goto heap_overflow;
140 }
141 tovisit->pt0 = pt0;
142 tovisit->pt0_end = pt0_end;
143 tovisit->ptf = ptf;
144 tovisit->oldv = *pt0;
145 tovisit->ground = ground;
146 /* fool the system into thinking we had a variable there */
147 *pt0 = AbsPair(HR);
148 tovisit ++;
149#else
150 if (pt0 < pt0_end) {
151 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
152 goto heap_overflow;
153 }
154 tovisit->pt0 = pt0;
155 tovisit->pt0_end = pt0_end;
156 tovisit->ptf = ptf;
157 tovisit->ground = ground;
158 tovisit ++;
159 }
160#endif
161 ground = TRUE;
162 pt0 = ap2 - 1;
163 pt0_end = ap2 + 1;
164 ptf = HR;
165 HR += 2;
166 if (HR > ASP - 2048) {
167 goto overflow;
168 }
169 } else if (IsApplTerm(d0)) {
170 register Functor f;
171 register CELL *ap2;
172 /* store the terms to visit */
173 ap2 = RepAppl(d0);
174 if (ap2 >= HB && ap2 <= HR) {
175 /* If this is newer than the current term, just reuse */
176 *ptf++ = d0;
177 continue;
178 }
179 f = (Functor)(*ap2);
180
181 if (IsExtensionFunctor(f)) {
182#if MULTIPLE_STACKS
183 if (f == FunctorDBRef) {
184 DBRef entryref = DBRefOfTerm(d0);
185 if (entryref->Flags & LogUpdMask) {
186 LogUpdClause *luclause = (LogUpdClause *)entryref;
187 PELOCK(100,luclause->ClPred);
188 UNLOCK(luclause->ClPred->PELock);
189 } else {
190 LOCK(entryref->lock);
191 TRAIL_REF(entryref); /* So that fail will erase it */
192 INC_DBREF_COUNT(entryref);
193 UNLOCK(entryref->lock);
194 }
195 *ptf++ = d0; /* you can just copy other extensions. */
196 } else
197#endif
198 if (!share) {
199 UInt sz;
200
201 *ptf++ = AbsAppl(HR); /* you can just copy other extensions. */
202 /* make sure to copy floats */
203 if (f== FunctorDouble) {
204 sz = sizeof(Float)/sizeof(CELL)+2;
205 } else if (f== FunctorLongInt) {
206 sz = 3;
207 } else if (f== FunctorString) {
208 sz = 3+ap2[1];
209 } else {
210 CELL *pt = ap2+1;
211 sz = 2+sizeof(MP_INT)+(((MP_INT *)(pt+1))->_mp_alloc*sizeof(mp_limb_t));
212 }
213 if (HR+sz > ASP - 2048) {
214 goto overflow;
215 }
216 memcpy((void *)HR, (void *)ap2, sz*sizeof(CELL));
217 HR += sz;
218 } else {
219 *ptf++ = d0; /* you can just copy other extensions. */
220 }
221 continue;
222 }
223 *ptf = AbsAppl(HR);
224 ptf++;
225 /* store the terms to visit */
226#ifdef RATIONAL_TREES
227 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
228 goto heap_overflow;
229 }
230 tovisit->pt0 = pt0;
231 tovisit->pt0_end = pt0_end;
232 tovisit->ptf = ptf;
233 tovisit->oldv = *pt0;
234 tovisit->ground = ground;
235 /* fool the system into thinking we had a variable there */
236 *pt0 = AbsAppl(HR);
237 tovisit ++;
238#else
239 if (pt0 < pt0_end) {
240 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
241 goto heap_overflow;
242 }
243 tovisit->pt0 = pt0;
244 tovisit->pt0_end = pt0_end;
245 tovisit->ptf = ptf;
246 tovisit->ground = ground;
247 tovisit ++;
248 }
249#endif
250 ground = (f != FunctorMutable);
251 d0 = ArityOfFunctor(f);
252 pt0 = ap2;
253 pt0_end = ap2 + d0;
254 /* store the functor for the new term */
255 HR[0] = (CELL)f;
256 ptf = HR+1;
257 HR += 1+d0;
258 if (HR > ASP - 2048) {
259 goto overflow;
260 }
261 } else {
262 /* just copy atoms or integers */
263 *ptf++ = d0;
264 }
265 continue;
266 }
267
268 derefa_body(d0, ptd0, copy_term_unk, copy_term_nvar);
269 ground = FALSE;
270 if (ptd0 >= HLow && ptd0 < HR) {
271 /* we have already found this cell */
272 *ptf++ = (CELL) ptd0;
273 } else
274#if COROUTINING
275 if (newattvs && IsAttachedTerm((CELL)ptd0)) {
276 /* if unbound, call the standard copy term routine */
277 struct cp_frame *bp;
278
279 CELL new;
280
281 bp = tovisit;
282 if (!GLOBAL_attas[ExtFromCell(ptd0)].copy_term_op(ptd0, &bp, ptf PASS_REGS)) {
283 goto overflow;
284 }
285 tovisit = bp;
286 new = *ptf;
287 Bind_NonAtt(ptd0, new);
288 ptf++;
289 } else {
290#endif
291 /* first time we met this term */
292 RESET_VARIABLE(ptf);
293 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
294 /* Trail overflow */
295 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
296 goto trail_overflow;
297 }
298 }
299 Bind_NonAtt(ptd0, (CELL)ptf);
300 ptf++;
301#ifdef COROUTINING
302 }
303#endif
304 }
305 /* Do we still have compound terms to visit */
306 if (tovisit > tovisit0) {
307 tovisit --;
308 if (ground && share) {
309 CELL old = tovisit->oldv;
310 CELL *newp = tovisit->ptf-1;
311 CELL new = *newp;
312
313 *newp = old;
314 if (IsApplTerm(new))
315 HR = RepAppl(new);
316 else
317 HR = RepPair(new);
318 }
319 pt0 = tovisit->pt0;
320 pt0_end = tovisit->pt0_end;
321 ptf = tovisit->ptf;
322#ifdef RATIONAL_TREES
323 *pt0 = tovisit->oldv;
324#endif
325 ground = (ground && tovisit->ground);
326 goto loop;
327 }
328
329 /* restore our nice, friendly, term to its original state */
330 clean_dirty_tr(TR0 PASS_REGS);
331 HB = HB0;
332 return ground;
333
334 overflow:
335 /* oops, we're in trouble */
336 HR = HLow;
337 /* we've done it */
338 /* restore our nice, friendly, term to its original state */
339 HB = HB0;
340#ifdef RATIONAL_TREES
341 while (tovisit > tovisit0) {
342 tovisit --;
343 pt0 = tovisit->pt0;
344 pt0_end = tovisit->pt0_end;
345 ptf = tovisit->ptf;
346 *pt0 = tovisit->oldv;
347 }
348#endif
349 reset_trail(TR0);
350 /* follow chain of multi-assigned variables */
351 return -1;
352
353trail_overflow:
354 /* oops, we're in trouble */
355 HR = HLow;
356 /* we've done it */
357 /* restore our nice, friendly, term to its original state */
358 HB = HB0;
359#ifdef RATIONAL_TREES
360 while (tovisit > tovisit0) {
361 tovisit --;
362 pt0 = tovisit->pt0;
363 pt0_end = tovisit->pt0_end;
364 ptf = tovisit->ptf;
365 *pt0 = tovisit->oldv;
366 }
367#endif
368 {
369 tr_fr_ptr oTR = TR;
370 reset_trail(TR0);
371 if (!Yap_growtrail((oTR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
372 return -4;
373 }
374 return -2;
375 }
376
377 heap_overflow:
378 /* oops, we're in trouble */
379 HR = HLow;
380 /* we've done it */
381 /* restore our nice, friendly, term to its original state */
382 HB = HB0;
383#ifdef RATIONAL_TREES
384 while (tovisit > tovisit0) {
385 tovisit --;
386 pt0 = tovisit->pt0;
387 pt0_end = tovisit->pt0_end;
388 ptf = tovisit->ptf;
389 *pt0 = tovisit->oldv;
390 }
391#endif
392 reset_trail(TR0);
393 LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)tovisit0;
394 return -3;
395}
396
397
398static Term
399CopyTerm(Term inp, UInt arity, int share, int newattvs USES_REGS) {
400 Term t = Deref(inp);
401 tr_fr_ptr TR0 = TR;
402
403 if (IsVarTerm(t)) {
404#if COROUTINING
405 if (newattvs && IsAttachedTerm(t)) {
406 CELL *Hi;
407 int res;
408 restart_attached:
409
410 *HR = t;
411 Hi = HR+1;
412 HR += 2;
413 if ((res = copy_complex_term(Hi-2, Hi-1, share, newattvs, Hi, Hi PASS_REGS)) < 0) {
414 HR = Hi-1;
415 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
416 return FALSE;
417 goto restart_attached;
418 }
419 return Hi[0];
420 }
421#endif
422 return MkVarTerm();
423 } else if (IsPrimitiveTerm(t)) {
424 return t;
425 } else if (IsPairTerm(t)) {
426 Term tf;
427 CELL *ap;
428 CELL *Hi;
429
430 restart_list:
431 ap = RepPair(t);
432 Hi = HR;
433 tf = AbsPair(HR);
434 HR += 2;
435 {
436 int res;
437 if ((res = copy_complex_term(ap-1, ap+1, share, newattvs, Hi, Hi PASS_REGS)) < 0) {
438 HR = Hi;
439 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
440 return FALSE;
441 goto restart_list;
442 } else if (res && share) {
443 HR = Hi;
444 return t;
445 }
446 }
447 return tf;
448 } else {
449 Functor f = FunctorOfTerm(t);
450 Term tf;
451 CELL *HB0;
452 CELL *ap;
453
454 restart_appl:
455 f = FunctorOfTerm(t);
456 HB0 = HR;
457 ap = RepAppl(t);
458 tf = AbsAppl(HR);
459 HR[0] = (CELL)f;
460 HR += 1+ArityOfFunctor(f);
461 if (HR > ASP-128) {
462 HR = HB0;
463 if ((t = handle_cp_overflow(-1, TR0, arity, t))== 0L)
464 return FALSE;
465 goto restart_appl;
466 } else {
467 int res;
468
469 if ((res = copy_complex_term(ap, ap+ArityOfFunctor(f), share, newattvs, HB0+1, HB0 PASS_REGS)) < 0) {
470 HR = HB0;
471 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
472 return FALSE;
473 goto restart_appl;
474 } else if (res && share && FunctorOfTerm(t) != FunctorMutable) {
475 HR = HB0;
476 return t;
477 }
478 }
479 return tf;
480 }
481}
482
483static Int
484p_copy_term( USES_REGS1 ) /* copy term t to a new instance */
485{
486 Term t = CopyTerm(ARG1, 2, TRUE, TRUE PASS_REGS);
487 if (t == 0L)
488 return FALSE;
489 /* be careful, there may be a stack shift here */
490 return Yap_unify(ARG2,t);
491}
492
493static Int
494p_duplicate_term( USES_REGS1 ) /* copy term t to a new instance */
495{
496 Term t = CopyTerm(ARG1, 2, FALSE, TRUE PASS_REGS);
497 if (t == 0L)
498 return FALSE;
499 /* be careful, there may be a stack shift here */
500 return Yap_unify(ARG2,t);
501}
502
503
504static Int
505p_copy_term_no_delays( USES_REGS1 ) /* copy term t to a new instance */
506{
507 Term t = CopyTerm(ARG1, 2, TRUE, FALSE PASS_REGS);
508 if (t == 0L) {
509 return FALSE;
510 }
511 /* be careful, there may be a stack shift here */
512 return(Yap_unify(ARG2,t));
513}
514#endif
515
516
517typedef struct copy_frame {
518 CELL *pt0;
519 CELL *pt0_end;
520 CELL *ptf;
522
523static Term *
524add_to_list( Term *out_e, Term v, Term t USES_REGS)
525{
526 Term ta[2], tv;
527
528 ta[0] = v;
529 ta[1] = t;
530 *out_e = tv = MkPairTerm(Yap_MkApplTerm( FunctorEq, 2, ta ), TermNil);
531 return RepPair(tv)+1;
532}
533
534static int
535break_rationals_complex_term(CELL *pt0, CELL *pt0_end, CELL *ptf, Term *of, Term oi, CELL *HLow USES_REGS)
536{
537
538 struct copy_frame *tovisit0, *tovisit = (struct copy_frame *)Yap_PreAllocCodeSpace();
539 CELL *HB0 = HB;
540 tr_fr_ptr TR0 = TR;
541 CELL new = 0L;
542
543 HB = HLow;
544 tovisit0 = tovisit;
545 loop:
546 while (pt0 < pt0_end) {
547 register CELL d0;
548 register CELL *ptd0;
549 ++ pt0;
550 ptd0 = pt0;
551 d0 = *ptd0;
552 if (new) {
553 /* mark cell as pointing to new copy */
554 /* we can only mark after reading the value of the first argument */
555 MaBind(pt0, new);
556 new = 0L;
557 }
558 deref_head(d0, break_rationals_unk);
559 break_rationals_nvar:
560 {
561 CELL first;
562 CELL *newp;
563 if (IsPairTerm(d0)) {
564 CELL *ap2 = RepPair(d0);
565
566 if (IsVarTerm(first = *ap2) && (newp = (CELL*)first) && newp >= HB && newp < HR) {
567 // found a marked term:
568 found_term:
569 if (!IsVarTerm(*newp)) {
570 Term v = (CELL)newp, t = *newp;
571 RESET_VARIABLE(newp);
572 of = add_to_list( of, v, t PASS_REGS);
573 }
574 *ptf++ = (CELL)newp;
575 continue;
576 }
577 new = (CELL)ptf;
578 *ptf++ = AbsPair(HR);
579 if (pt0 < pt0_end) {
580 if (tovisit+1 >= (struct copy_frame *)AuxSp) {
581 goto heap_overflow;
582 }
583 tovisit->pt0 = pt0;
584 tovisit->pt0_end = pt0_end;
585 tovisit->ptf = ptf;
586 tovisit ++;
587 }
588 pt0 = ap2 - 1;
589 pt0_end = ap2 + 1;
590 ptf = HR;
591 HR += 2;
592 if (HR > ASP - 2048) {
593 goto overflow;
594 }
595 } else if (IsApplTerm(d0)) {
596 register Functor f;
597 register CELL *ap2;
598 /* store the terms to visit */
599 ap2 = RepAppl(d0);
600 f = (Functor)(*ap2);
601 if (IsExtensionFunctor(f)) {
602 *ptf++ = d0; /* you can just share extensions, what about DB? */
603 continue;
604 }
605 if (IsVarTerm(first = ap2[1]) && (newp = (CELL*)first) && newp >= HB && newp < HR) {
606 goto found_term;
607 }
608 // new
609 /* store the terms to visit */
610 new = (CELL)ptf;
611 *ptf++ = AbsAppl(HR);
612 if (pt0 < pt0_end) {
613 if (tovisit+1 >= (struct copy_frame *)AuxSp) {
614 goto heap_overflow;
615 }
616 tovisit->pt0 = pt0;
617 tovisit->pt0_end = pt0_end;
618 tovisit->ptf = ptf;
619 tovisit ++;
620 }
621 d0 = ArityOfFunctor(f);
622 pt0 = ap2;
623 pt0_end = ap2 + d0;
624 /* store the functor for the new term */
625 HR[0] = (CELL)f;
626 ptf = HR+1;
627 HR += 1+d0;
628 if (HR > ASP - 2048) {
629 goto overflow;
630 }
631 } else {
632 /* just copy atoms or integers */
633 *ptf++ = d0;
634 }
635 continue;
636 }
637
638 derefa_body(d0, ptd0, break_rationals_unk, break_rationals_nvar);
639 *ptf++ = d0;
640 }
641 /* Do we still have compound terms to visit */
642 if (tovisit > tovisit0) {
643 tovisit --;
644 pt0 = tovisit->pt0;
645 pt0_end = tovisit->pt0_end;
646 ptf = tovisit->ptf;
647 goto loop;
648 }
649
650 /* restore our nice, friendly, term to its original state */
651 HB = HB0;
652 reset_trail(TR0);
653 RESET_VARIABLE(of);
654 Yap_unify((CELL)of, oi);
655 return TRUE;
656
657 overflow:
658 /* oops, we're in trouble */
659 HR = HLow;
660 /* we've done it */
661 /* restore our nice, friendly, term to its original state */
662 HB = HB0;
663#ifdef RATIONAL_TREES
664 while (tovisit > tovisit0) {
665 tovisit --;
666 pt0 = tovisit->pt0;
667 pt0_end = tovisit->pt0_end;
668 ptf = tovisit->ptf;
669 }
670#endif
671 reset_trail(TR0);
672 /* follow chain of multi-assigned variables */
673 return -1;
674
675 heap_overflow:
676 /* oops, we're in trouble */
677 HR = HLow;
678 /* we've done it */
679 /* restore our nice, friendly, term to its original state */
680 HB = HB0;
681#ifdef RATIONAL_TREES
682 while (tovisit > tovisit0) {
683 tovisit --;
684 pt0 = tovisit->pt0;
685 pt0_end = tovisit->pt0_end;
686 ptf = tovisit->ptf;
687 }
688#endif
689 reset_trail(TR0);
690 LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)tovisit0;
691 return -3;
692}
693
694
695static Term
696BreakRational(Term inp, UInt arity, Term *of, Term oi USES_REGS) {
697 Term t = Deref(inp);
698 tr_fr_ptr TR0 = TR;
699
700 if (IsVarTerm(t)) {
701 return t;
702 } else if (IsPrimitiveTerm(t)) {
703 return t;
704 } else {
705 CELL *ap;
706 CELL *Hi = HR;
707
708 restart_term:
709 ap = &t;
710 Hi = HR++;
711 {
712 int res;
713
714 if ((res = break_rationals_complex_term(ap-1, ap, Hi, of, oi, Hi PASS_REGS)) < 0) {
715 HR = Hi;
716 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
717 return FALSE;
718 goto restart_term;
719 }
720 }
721 return Hi[0];
722 }
723}
724
725static Int
726p_break_rational( USES_REGS1 )
727{
728 Term tf, t1=Deref(ARG1);
729 if (IsVarTerm(t1)
730 || IsAtomicTerm(t1))
731 return Yap_unify(t1,ARG2) && Yap_unify(ARG3,ARG4);
732 return Yap_unify(ARG2, BreakRational(ARG1, 4, &tf, ARG4 PASS_REGS)) &&
733 Yap_unify(tf, ARG3);
734}
735
736
737static Int
738p_break_rational3( USES_REGS1 )
739{
740 Term tf, t1=Deref(ARG1);
741 if (IsVarTerm(t1)
742 || IsAtomicTerm(t1))
743 return Yap_unify(t1,ARG2) && Yap_unify(ARG3,TermNil);
744 return Yap_unify(ARG2, BreakRational(ARG1, 4, &tf, TermNil PASS_REGS)) &&
745 Yap_unify(tf, ARG3);
746}
747
748
749/*
750 FAST EXPORT ROUTINE. Export a Prolog term to something like:
751
752 CELL 0: offset for start of term
753 CELL 1: size of actual term (to be copied to stack)
754 CELL 2: the original term (just for reference)
755
756 Atoms and functors:
757 - atoms are either:
758 0 and a char *string
759 -1 and a wchar_t *string
760 - functors are a CELL with arity and a string.
761
762 Compiled Term.
763
764 */
765
766static inline
767CELL *CellDifH(CELL *hptr, CELL *hlow)
768{
769 return (CELL *)((char *)hptr-(char *)hlow);
770}
771
772#define AdjustSizeAtom(X) (((CELL)(X)+(8-1)) & ~(8-1))
773
774static inline
775CELL *AtomAdjustSize(CELL *x, char *buf)
776{
777 UInt offset = (char *)x-buf;
778 return (CELL*)(buf+AdjustSizeAtom(offset));
779}
780
781/* export an atom from the symbol table to a buffer */
782static inline
783Atom export_atom(Atom at, char **hpp, char *buf, size_t len)
784{
785 char *ptr, *p0;
786 size_t sz;
787
788 ptr = *hpp;
789 ptr = (char *)AtomAdjustSize((CELL*)ptr, buf);
790
791 p0 = ptr;
792 *ptr++ = 0;
793 sz = strlen(RepAtom(at)->StrOfAE);
794 if (sz + 1 >= len)
795 return (Atom)NULL;
796 strcpy(ptr, RepAtom(at)->StrOfAE);
797 *hpp = ptr+(sz+1);
798 return (Atom)(p0-buf);
799}
800
801/* place a buffer: first arity then the atom */
802static inline
803Functor export_functor(Functor f, char **hpp, char *buf, size_t len)
804{
805 CELL *hptr = AtomAdjustSize((CELL *)*hpp, buf);
806 UInt arity = ArityOfFunctor(f);
807 if (2*sizeof(CELL) >= len)
808 return NULL;
809 hptr[0] = arity;
810 *hpp = (char *)(hptr+1);
811 if (!export_atom(NameOfFunctor(f), hpp, buf, len))
812 return NULL;
813 /* increment so that it cannot be mistaken with a functor on the stack,
814 (increment is used as a tag ........01
815 */
816 return (Functor)(((char *)hptr-buf)+1);
817}
818
819#define export_derefa_body(D,A,LabelUnk,LabelNonVar) \
820 do { \
821 if ((CELL *)(D) < CellDifH(HR,HLow)) { (A) = (CELL *)(D); break; } \
822 (A) = (CELL *)(D); \
823 (D) = *(CELL *)(D); \
824 if(!IsVarTerm(D)) goto LabelNonVar; \
825 LabelUnk: ; \
826 } while (Unsigned(A) != (D))
827
828
829static int
830export_term_to_buffer(Term inpt, char *buf, char *bptr, CELL *t0 , CELL *tf, size_t len)
831{
832 char *td = bptr;
833 CELL *bf = (CELL *)buf;
834 if (buf + len < (char *)((CELL *)td + (tf-t0))) {
835 return FALSE;
836 }
837 memcpy((void *)td, (void *)t0, (tf-t0)* sizeof(CELL));
838 bf[0] = (td-buf);
839 bf[1] = (tf-t0);
840 bf[2] = inpt;
841 return bf[0]+sizeof(CELL)*bf[1];
842}
843
844
845static size_t
846export_complex_term(Term tf, CELL *pt0, CELL *pt0_end, char * buf, size_t len0, int newattvs, CELL *ptf, CELL *HLow USES_REGS)
847{
848 struct cp_frame *tovisit0, *tovisit = (struct cp_frame *)Yap_PreAllocCodeSpace();
849 CELL *HB0 = HB;
850 tr_fr_ptr TR0 = TR;
851 int ground = TRUE;
852 char *bptr = buf+ 3*sizeof(CELL);
853 size_t len = len0;
854
855 HB = HLow;
856 tovisit0 = tovisit;
857 loop:
858 while (pt0 < pt0_end) {
859 register CELL d0;
860 register CELL *ptd0;
861 ++ pt0;
862 ptd0 = pt0;
863 d0 = *ptd0;
864 deref_head(d0, export_term_unk);
865 export_term_nvar:
866 {
867 if (IsPairTerm(d0)) {
868 CELL *ap2 = RepPair(d0);
869 if (ap2 < CellDifH(HR,HLow)) {
870 /* If this is newer than the current term, just reuse */
871 *ptf++ = d0;
872 continue;
873 }
874 *ptf = AbsPair(CellDifH(HR,HLow));
875 ptf++;
876#ifdef RATIONAL_TREES
877 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
878 goto heap_overflow;
879 }
880 tovisit->pt0 = pt0;
881 tovisit->pt0_end = pt0_end;
882 tovisit->ptf = ptf;
883 tovisit->oldv = *pt0;
884 tovisit->ground = ground;
885 /* fool the system into thinking we had a variable there */
886 *pt0 = AbsPair(CellDifH(HR,HLow));
887 tovisit ++;
888#else
889 if (pt0 < pt0_end) {
890 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
891 goto heap_overflow;
892 }
893 tovisit->pt0 = pt0;
894 tovisit->pt0_end = pt0_end;
895 tovisit->ptf = ptf;
896 tovisit->ground = ground;
897 tovisit ++;
898 }
899#endif
900 pt0 = ap2 - 1;
901 pt0_end = ap2 + 1;
902 ptf = HR;
903 HR += 2;
904 if (HR > ASP - 2048) {
905 goto overflow;
906 }
907 } else if (IsApplTerm(d0)) {
908 register Functor f;
909 register CELL *ap2;
910 /* store the terms to visit */
911 ap2 = RepAppl(d0);
912 if (ap2 < CellDifH(HR,HLow)) {
913 /* If this is newer than the current term, just reuse */
914 *ptf++ = d0;
915 continue;
916 }
917 f = (Functor)(*ap2);
918
919 *ptf++ = AbsAppl(CellDifH(HR,HLow));
920 if (IsExtensionFunctor(f)) {
921 UInt sz;
922
923 /* make sure to export floats */
924 if (f== FunctorDouble) {
925 sz = sizeof(Float)/sizeof(CELL)+2;
926 } else if (f== FunctorLongInt) {
927 sz = 3;
928 } else if (f== FunctorString) {
929 sz = 3+ap2[1];
930 } else {
931 CELL *pt = ap2+1;
932 sz = 2+sizeof(MP_INT)+(((MP_INT *)(pt+1))->_mp_alloc*sizeof(mp_limb_t));
933 }
934 if (HR+sz > ASP - 2048) {
935 goto overflow;
936 }
937 memcpy((void *)HR, (void *)ap2, sz*sizeof(CELL));
938 HR += sz;
939 continue;
940 }
941 /* store the terms to visit */
942#ifdef RATIONAL_TREES
943 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
944 goto heap_overflow;
945 }
946 tovisit->pt0 = pt0;
947 tovisit->pt0_end = pt0_end;
948 tovisit->ptf = ptf;
949 tovisit->oldv = *pt0;
950 tovisit->ground = ground;
951 /* fool the system into thinking we had a variable there */
952 *pt0 = AbsAppl(HR);
953 tovisit ++;
954#else
955 if (pt0 < pt0_end) {
956 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
957 goto heap_overflow;
958 }
959 tovisit->pt0 = pt0;
960 tovisit->pt0_end = pt0_end;
961 tovisit->ptf = ptf;
962 tovisit->ground = ground;
963 tovisit ++;
964 }
965#endif
966 ground = (f != FunctorMutable);
967 d0 = ArityOfFunctor(f);
968 pt0 = ap2;
969 pt0_end = ap2 + d0;
970 /* store the functor for the new term */
971 ptf = HR+1;
972 HR += 1+d0;
973 if (HR > ASP - 2048) {
974 goto overflow;
975 }
976 ptf[-1] = (CELL)export_functor(f, &bptr, buf, len);
977 len = len0 - (bptr-buf);
978 if (HR > ASP - 2048) {
979 goto overflow;
980 }
981 } else {
982 if (IsAtomTerm(d0)) {
983 *ptf = MkAtomTerm(export_atom(AtomOfTerm(d0), &bptr, buf, len));
984 ptf++;
985 len = len0 - (bptr-buf);
986 } else {
987 *ptf++ = d0;
988 }
989 }
990 continue;
991 }
992
993 export_derefa_body(d0, ptd0, export_term_unk, export_term_nvar);
994 ground = FALSE;
995 if (ptd0 < CellDifH(HR,HLow)) {
996 /* we have already found this cell */
997 *ptf++ = (CELL) ptd0;
998 } else {
999#if COROUTINING
1000 if (newattvs && IsAttachedTerm((CELL)ptd0) && FALSE) {
1001 /* if unbound, call the standard export term routine */
1002 struct cp_frame *bp;
1003
1004 CELL new;
1005
1006 bp = tovisit;
1007 if (!GLOBAL_attas[ExtFromCell(ptd0)].copy_term_op(ptd0, &bp, ptf PASS_REGS)) {
1008 goto overflow;
1009 }
1010 tovisit = bp;
1011 new = *ptf;
1012 Bind_NonAtt(ptd0, new);
1013 ptf++;
1014 } else {
1015#endif
1016 /* first time we met this term */
1017 *ptf = (CELL)CellDifH(ptf,HLow);
1018 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
1019 /* Trail overflow */
1020 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
1021 goto trail_overflow;
1022 }
1023 }
1024 Bind_NonAtt(ptd0, (CELL)ptf);
1025 ptf++;
1026#ifdef COROUTINING
1027 }
1028#endif
1029 }
1030 }
1031 /* Do we still have compound terms to visit */
1032 if (tovisit > tovisit0) {
1033 tovisit --;
1034 pt0 = tovisit->pt0;
1035 pt0_end = tovisit->pt0_end;
1036 ptf = tovisit->ptf;
1037#ifdef RATIONAL_TREES
1038 *pt0 = tovisit->oldv;
1039#endif
1040 ground = (ground && tovisit->ground);
1041 goto loop;
1042 }
1043
1044 /* restore our nice, friendly, term to its original state */
1045 clean_dirty_tr(TR0 PASS_REGS);
1046 HB = HB0;
1047 return export_term_to_buffer(tf, buf, bptr, HLow, HR, len0);
1048
1049 overflow:
1050 /* oops, we're in trouble */
1051 HR = HLow;
1052 /* we've done it */
1053 /* restore our nice, friendly, term to its original state */
1054 HB = HB0;
1055#ifdef RATIONAL_TREES
1056 while (tovisit > tovisit0) {
1057 tovisit --;
1058 pt0 = tovisit->pt0;
1059 pt0_end = tovisit->pt0_end;
1060 ptf = tovisit->ptf;
1061 *pt0 = tovisit->oldv;
1062 }
1063#endif
1064 reset_trail(TR0);
1065 /* follow chain of multi-assigned variables */
1066 return -1;
1067
1068trail_overflow:
1069 /* oops, we're in trouble */
1070 HR = HLow;
1071 /* we've done it */
1072 /* restore our nice, friendly, term to its original state */
1073 HB = HB0;
1074#ifdef RATIONAL_TREES
1075 while (tovisit > tovisit0) {
1076 tovisit --;
1077 pt0 = tovisit->pt0;
1078 pt0_end = tovisit->pt0_end;
1079 ptf = tovisit->ptf;
1080 *pt0 = tovisit->oldv;
1081 }
1082#endif
1083 {
1084 tr_fr_ptr oTR = TR;
1085 reset_trail(TR0);
1086 if (!Yap_growtrail((oTR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
1087 return -4;
1088 }
1089 return -2;
1090 }
1091
1092 heap_overflow:
1093 /* oops, we're in trouble */
1094 HR = HLow;
1095 /* we've done it */
1096 /* restore our nice, friendly, term to its original state */
1097 HB = HB0;
1098#ifdef RATIONAL_TREES
1099 while (tovisit > tovisit0) {
1100 tovisit --;
1101 pt0 = tovisit->pt0;
1102 pt0_end = tovisit->pt0_end;
1103 ptf = tovisit->ptf;
1104 *pt0 = tovisit->oldv;
1105 }
1106#endif
1107 reset_trail(TR0);
1108 LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)tovisit0;
1109 return -3;
1110}
1111
1112static size_t
1113ExportTerm(Term inp, char * buf, size_t len, UInt arity, int newattvs USES_REGS) {
1114 Term t = Deref(inp);
1115 tr_fr_ptr TR0 = TR;
1116 size_t res = 0;
1117 CELL *Hi = HR;
1118
1119 do {
1120 if (IsVarTerm(t) || IsIntTerm(t)) {
1121 return export_term_to_buffer(t, buf, buf+ 3*sizeof(CELL), &inp, &inp, len);
1122 }
1123 if (IsAtomTerm(t)) {
1124 Atom at = AtomOfTerm(t);
1125 char *b = buf+3*sizeof(CELL);
1126 export_atom(at, &b, b, len-3*sizeof(CELL));
1127 return export_term_to_buffer(t, buf, b, &inp, &inp, len);
1128 }
1129 if ((Int)res < 0) {
1130 HR = Hi;
1131 TR = TR0;
1132 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
1133 return res;
1134 }
1135 Hi = HR;
1136 TR0 = TR;
1137 res = export_complex_term(inp, &t-1, &t, buf, len, newattvs, Hi, Hi PASS_REGS);
1138 } while ((Int)res < 0);
1139 return res;
1140}
1141
1142size_t
1143Yap_ExportTerm(Term inp, char * buf, size_t len, UInt arity) {
1144 CACHE_REGS
1145 return ExportTerm(inp, buf, len, arity, TRUE PASS_REGS);
1146}
1147
1148
1149static CELL *
1150ShiftPtr(CELL t, char *base)
1151{
1152 return (CELL *)(base+t);
1153}
1154
1155static Atom
1156addAtom(Atom t, char *buf)
1157{
1158 char *s = buf+(UInt)t;
1159
1160 if (!*s) {
1161 return Yap_LookupAtom(s+1);
1162 }
1163 return NULL;
1164}
1165
1166static UInt
1167FetchFunctor(CELL *pt, char *buf)
1168{
1169 CELL *ptr = (CELL *)(buf+(*pt-1));
1170 // do arity first
1171 UInt arity = *ptr++;
1172 Atom name, at;
1173 // and then an atom
1174 ptr = AtomAdjustSize(ptr, buf);
1175 name = (Atom)((char *)ptr-buf);
1176 at = addAtom(name, buf);
1177 *pt = (CELL)Yap_MkFunctor(at, arity);
1178 return arity;
1179}
1180
1181
1182static CELL *import_compound(CELL *hp, char *abase, char *buf, CELL *amax);
1183static CELL *import_pair(CELL *hp, char *abase, char *buf, CELL *amax);
1184
1185static CELL *
1186import_arg(CELL *hp, char *abase, char *buf, CELL *amax)
1187{
1188 Term t = *hp;
1189 if (IsVarTerm(t)) {
1190 hp[0] = (CELL)ShiftPtr(t, abase);
1191 } else if (IsAtomTerm(t)) {
1192 hp[0] = MkAtomTerm(addAtom(AtomOfTerm(t), buf));
1193 } else if (IsPairTerm(t)) {
1194 CELL *newp = ShiftPtr((CELL)RepPair(t), abase);
1195 hp[0] = AbsPair(newp);
1196 if (newp > amax) {
1197 amax = import_pair(newp, abase, buf, newp);
1198 }
1199 } else if (IsApplTerm(t)) {
1200 CELL *newp = ShiftPtr((CELL)RepAppl(t), abase);
1201 hp[0] = AbsAppl(newp);
1202 if (newp > amax) {
1203 amax = import_compound(newp, abase, buf, newp);
1204 }
1205 }
1206 return amax;
1207}
1208
1209static CELL *
1210import_compound(CELL *hp, char *abase, char *buf, CELL *amax)
1211{
1212 Functor f = (Functor)*hp;
1213 UInt ar, i;
1214
1215 if (!((CELL)f & 1) && IsExtensionFunctor(f))
1216 return amax;
1217 ar = FetchFunctor(hp, buf);
1218 for (i=1; i<=ar; i++) {
1219 amax = import_arg(hp+i, abase, buf, amax);
1220 }
1221 return amax;
1222}
1223
1224static CELL *
1225import_pair(CELL *hp, char *abase, char *buf, CELL *amax)
1226{
1227 amax = import_arg(hp, abase, buf, amax);
1228 amax = import_arg(hp+1, abase, buf, amax);
1229 return amax;
1230}
1231
1232Term
1233Yap_ImportTerm(char * buf) {
1234 CACHE_REGS
1235 CELL *bc = (CELL *)buf;
1236 size_t sz = bc[1];
1237 Term tinp, tret;
1238 tinp = bc[2];
1239 if (IsVarTerm(tinp))
1240 return MkVarTerm();
1241 else if (IsIntTerm(tinp))
1242 return tinp;
1243 else if (IsAtomTerm(tinp)) {
1244 tret = MkAtomTerm(addAtom(NULL,(char *)(bc+3)));
1245 return tret;
1246 }
1247 // call the gc/stack shifter mechanism
1248 // if not enough stack available
1249 while (HR + sz > ASP - 4096) {
1250 if (!Yap_dogc(PASS_REGS1)) {
1251 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
1252 return 0L;
1253 }
1254 }
1255 memcpy(HR, buf+bc[0], sizeof(CELL)*sz);
1256 if (IsApplTerm(tinp)) {
1257 tret = AbsAppl(HR);
1258 import_compound(HR, (char *)HR, buf, HR);
1259 } else {
1260 tret = AbsPair(HR);
1261 import_pair(HR, (char *)HR, buf, HR);
1262 }
1263 HR += sz;
1264 return tret;
1265}
1266
1267size_t
1268Yap_SizeOfExportedTerm(char * buf) {
1269 CELL *bc = (CELL *)buf;
1270
1271 return bc[0]+bc[1]*sizeof(CELL);
1272}
1273
1274static Int
1275p_export_term( USES_REGS1 )
1276{
1277 size_t sz = 4096, osz;
1278 char *export_buf;
1279 do {
1280 export_buf = malloc(sz);
1281 if (!export_buf)
1282 return FALSE;
1283 if (!(osz = Yap_ExportTerm(ARG1, export_buf, sz, 1))) {
1284 sz += 4096;
1285 free(export_buf);
1286 }
1287 } while (!osz);
1288 return Yap_unify(ARG3,MkIntegerTerm(osz)) &&
1289 Yap_unify(ARG2, MkIntegerTerm((Int)export_buf));
1290}
1291
1292static Int
1293p_import_term( USES_REGS1 )
1294{
1295 char *export_buf = (char *)IntegerOfTerm(Deref(ARG1));
1296 if (!export_buf)
1297 return FALSE;
1298 Int out = Yap_unify(ARG2,Yap_ImportTerm(export_buf));
1299 return out;
1300}
1301
1302static Int
1303p_kill_exported_term( USES_REGS1 )
1304{
1305 char *export_buf = (char *)IntegerOfTerm(Deref(ARG1));
1306 if (!export_buf)
1307 return FALSE;
1308 free(export_buf);
1309 return TRUE;
1310}
1311
1312
1313static Term vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, Term inp USES_REGS)
1314{
1315
1316 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
1317 register tr_fr_ptr TR0 = TR;
1318 CELL *InitialH = HR;
1319 CELL output = AbsPair(HR);
1320
1321 tovisit0 = tovisit;
1322 loop:
1323 while (pt0 < pt0_end) {
1324 register CELL d0;
1325 register CELL *ptd0;
1326 ++ pt0;
1327 ptd0 = pt0;
1328 d0 = *ptd0;
1329 deref_head(d0, vars_in_term_unk);
1330 vars_in_term_nvar:
1331 {
1332 if (IsPairTerm(d0)) {
1333 if (tovisit + 1024 >= (CELL **)AuxSp) {
1334 goto aux_overflow;
1335 }
1336#ifdef RATIONAL_TREES
1337 tovisit[0] = pt0;
1338 tovisit[1] = pt0_end;
1339 tovisit[2] = (CELL *)*pt0;
1340 tovisit += 3;
1341 *pt0 = TermNil;
1342#else
1343 if (pt0 < pt0_end) {
1344 tovisit[0] = pt0;
1345 tovisit[1] = pt0_end;
1346 tovisit += 2;
1347 }
1348#endif
1349 pt0 = RepPair(d0) - 1;
1350 pt0_end = RepPair(d0) + 1;
1351 } else if (IsApplTerm(d0)) {
1352 register Functor f;
1353 register CELL *ap2;
1354 /* store the terms to visit */
1355 ap2 = RepAppl(d0);
1356 f = (Functor)(*ap2);
1357 if (IsExtensionFunctor(f)) {
1358 continue;
1359 }
1360 /* store the terms to visit */
1361 if (tovisit + 1024 >= (CELL **)AuxSp) {
1362 goto aux_overflow;
1363 }
1364#ifdef RATIONAL_TREES
1365 tovisit[0] = pt0;
1366 tovisit[1] = pt0_end;
1367 tovisit[2] = (CELL *)*pt0;
1368 tovisit += 3;
1369 *pt0 = TermNil;
1370#else
1371 if (pt0 < pt0_end) {
1372 tovisit[0] = pt0;
1373 tovisit[1] = pt0_end;
1374 tovisit += 2;
1375 }
1376#endif
1377 d0 = ArityOfFunctor(f);
1378 pt0 = ap2;
1379 pt0_end = ap2 + d0;
1380 }
1381 continue;
1382 }
1383
1384
1385 derefa_body(d0, ptd0, vars_in_term_unk, vars_in_term_nvar);
1386 /* do or pt2 are unbound */
1387 *ptd0 = TermNil;
1388 /* leave an empty slot to fill in later */
1389 if (HR+1024 > ASP) {
1390 goto global_overflow;
1391 }
1392 HR[1] = AbsPair(HR+2);
1393 HR += 2;
1394 HR[-2] = (CELL)ptd0;
1395 /* next make sure noone will see this as a variable again */
1396 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
1397 /* Trail overflow */
1398 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
1399 goto trail_overflow;
1400 }
1401 }
1402 TrailTerm(TR++) = (CELL)ptd0;
1403 }
1404 /* Do we still have compound terms to visit */
1405 if (tovisit > tovisit0) {
1406#ifdef RATIONAL_TREES
1407 tovisit -= 3;
1408 pt0 = tovisit[0];
1409 pt0_end = tovisit[1];
1410 *pt0 = (CELL)tovisit[2];
1411#else
1412 tovisit -= 2;
1413 pt0 = tovisit[0];
1414 pt0_end = tovisit[1];
1415#endif
1416 goto loop;
1417 }
1418
1419 clean_tr(TR0 PASS_REGS);
1420 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1421 if (HR != InitialH) {
1422 /* close the list */
1423 Term t2 = Deref(inp);
1424 if (IsVarTerm(t2)) {
1425 RESET_VARIABLE(HR-1);
1426 Yap_unify((CELL)(HR-1),inp);
1427 } else {
1428 HR[-1] = t2; /* don't need to trail */
1429 }
1430 return(output);
1431 } else {
1432 return(inp);
1433 }
1434
1435 trail_overflow:
1436#ifdef RATIONAL_TREES
1437 while (tovisit > tovisit0) {
1438 tovisit -= 3;
1439 pt0 = tovisit[0];
1440 *pt0 = (CELL)tovisit[2];
1441 }
1442#endif
1443 LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL;
1444 LOCAL_Error_Size = (TR-TR0)*sizeof(tr_fr_ptr *);
1445 clean_tr(TR0 PASS_REGS);
1446 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1447 HR = InitialH;
1448 return 0L;
1449
1450 aux_overflow:
1451 LOCAL_Error_Size = (tovisit-tovisit0)*sizeof(CELL **);
1452#ifdef RATIONAL_TREES
1453 while (tovisit > tovisit0) {
1454 tovisit -= 3;
1455 pt0 = tovisit[0];
1456 *pt0 = (CELL)tovisit[2];
1457 }
1458#endif
1459 LOCAL_Error_TYPE = RESOURCE_ERROR_AUXILIARY_STACK;
1460 clean_tr(TR0 PASS_REGS);
1461 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1462 HR = InitialH;
1463 return 0L;
1464
1465 global_overflow:
1466#ifdef RATIONAL_TREES
1467 while (tovisit > tovisit0) {
1468 tovisit -= 3;
1469 pt0 = tovisit[0];
1470 *pt0 = (CELL)tovisit[2];
1471 }
1472#endif
1473 clean_tr(TR0 PASS_REGS);
1474 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1475 HR = InitialH;
1476 LOCAL_Error_TYPE = RESOURCE_ERROR_STACK;
1477 LOCAL_Error_Size = (ASP-HR)*sizeof(CELL);
1478 return 0L;
1479
1480}
1481
1482static int
1483expand_vts( int args USES_REGS )
1484{
1485 UInt expand = LOCAL_Error_Size;
1486 yap_error_number yap_errno = LOCAL_Error_TYPE;
1487
1488 LOCAL_Error_Size = 0;
1489 LOCAL_Error_TYPE = YAP_NO_ERROR;
1490 if (yap_errno == RESOURCE_ERROR_TRAIL) {
1491 /* Trail overflow */
1492 if (!Yap_growtrail(expand, FALSE)) {
1493 return FALSE;
1494 }
1495 } else if (yap_errno == RESOURCE_ERROR_AUXILIARY_STACK) {
1496 /* Aux space overflow */
1497 if (expand > 4*1024*1024)
1498 expand = 4*1024*1024;
1499 if (!Yap_ExpandPreAllocCodeSpace(expand, NULL, TRUE)) {
1500 return FALSE;
1501 }
1502 } else {
1503 if (!Yap_dogc(PASS_REGS1)) {
1504 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in term_variables");
1505 return FALSE;
1506 }
1507 }
1508 return TRUE;
1509}
1510
1511static Int
1512p_variables_in_term( USES_REGS1 ) /* variables in term t */
1513{
1514 Term out, inp;
1515 int count;
1516
1517
1518 restart:
1519 count = 0;
1520 inp = Deref(ARG2);
1521 while (!IsVarTerm(inp) && IsPairTerm(inp)) {
1522 Term t = HeadOfTerm(inp);
1523 if (IsVarTerm(t)) {
1524 CELL *ptr = VarOfTerm(t);
1525 *ptr = TermFoundVar;
1526 TrailTerm(TR++) = t;
1527 count++;
1528 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
1529 clean_tr(TR-count PASS_REGS);
1530 if (!Yap_growtrail(count*sizeof(tr_fr_ptr *), FALSE)) {
1531 return FALSE;
1532 }
1533 goto restart;
1534 }
1535 }
1536 inp = TailOfTerm(inp);
1537 }
1538 do {
1539 Term t = Deref(ARG1);
1540 if (IsVarTerm(t)) {
1541 out = AbsPair(HR);
1542 HR += 2;
1543 RESET_VARIABLE(HR-2);
1544 RESET_VARIABLE(HR-1);
1545 Yap_unify((CELL)(HR-2),ARG1);
1546 Yap_unify((CELL)(HR-1),ARG2);
1547 } else if (IsPrimitiveTerm(t))
1548 out = ARG2;
1549 else if (IsPairTerm(t)) {
1550 out = vars_in_complex_term(RepPair(t)-1,
1551 RepPair(t)+1, ARG2 PASS_REGS);
1552 }
1553 else {
1554 Functor f = FunctorOfTerm(t);
1555 out = vars_in_complex_term(RepAppl(t),
1556 RepAppl(t)+
1557 ArityOfFunctor(f), ARG2 PASS_REGS);
1558 }
1559 if (out == 0L) {
1560 if (!expand_vts( 3 PASS_REGS ))
1561 return FALSE;
1562 }
1563 } while (out == 0L);
1564 clean_tr(TR-count PASS_REGS);
1565 return Yap_unify(ARG3,out);
1566}
1567
1568#if 0
1569static Int
1570p_term_variables( USES_REGS1 ) /* variables in term t */
1571{
1572 Term out;
1573
1574 if (!Yap_IsListOrPartialListTerm(ARG2)) {
1575 Yap_ThrowError(TYPE_ERROR_LIST,ARG2,"term_variables/2");
1576 return FALSE;
1577 }
1578
1579 do {
1580 Term t = Deref(ARG1);
1581 if (IsVarTerm(t)) {
1582 Term out = Yap_MkNewPairTerm();
1583 return
1584 Yap_unify(t,HeadOfTerm(out)) &&
1585 Yap_unify(TermNil, TailOfTerm(out)) &&
1586 Yap_unify(out, ARG2);
1587 } else if (IsPrimitiveTerm(t)) {
1588 return Yap_unify(TermNil, ARG2);
1589 } else if (IsPairTerm(t)) {
1590 out = vars_in_complex_term(RepPair(t)-1,
1591 RepPair(t)+1, TermNil PASS_REGS);
1592 }
1593 else {
1594 Functor f = FunctorOfTerm(t);
1595 if (IsExtensionFunctor(f)) {
1596 out =
1597 out = vars_in_complex_term(RepAppl(t),
1598 RepAppl(t)+
1599 ArityOfFunctor(f), TermNil PASS_REGS);
1600 }
1601 if (out == 0L) {
1602 if (!expand_vts( 3 PASS_REGS ))
1603 return FALSE;
1604 }
1605 } while (out == 0L);
1606 return Yap_unify(ARG2,out);
1607}
1608
1609
1616static Term attvars_in_complex_term(register CELL *pt0, register CELL *pt0_end, Term inp USES_REGS)
1617{
1618
1619 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
1620 register tr_fr_ptr TR0 = TR;
1621 CELL *InitialH = HR;
1622 CELL output = AbsPair(HR);
1623
1624 tovisit0 = tovisit;
1625 loop:
1626 while (pt0 < pt0_end) {
1627 register CELL d0;
1628 register CELL *ptd0;
1629 ++ pt0;
1630 ptd0 = pt0;
1631 d0 = *ptd0;
1632 deref_head(d0, attvars_in_term_unk);
1633 attvars_in_term_nvar:
1634 {
1635 if (IsPairTerm(d0)) {
1636 if (tovisit + 1024 >= (CELL **)AuxSp) {
1637 goto aux_overflow;
1638 }
1639 {
1640 CELL *npt0 = RepPair(d0);
1641 if(IsAtomicTerm(Deref(npt0[0]))) {
1642 pt0 = npt0;
1643 pt0_end = pt0 + 1;
1644 continue;
1645 }
1646 }
1647#ifdef RATIONAL_TREES
1648 tovisit[0] = pt0;
1649 tovisit[1] = pt0_end;
1650 tovisit[2] = (CELL *)*pt0;
1651 tovisit += 3;
1652 *pt0 = TermNil;
1653#else
1654 if (pt0 < pt0_end) {
1655 tovisit[0] = pt0;
1656 tovisit[1] = pt0_end;
1657 tovisit += 2;
1658 }
1659#endif
1660 pt0 = RepPair(d0) - 1;
1661 pt0_end = pt0+2;
1662 } else if (IsApplTerm(d0)) {
1663 register Functor f;
1664 register CELL *ap2;
1665 /* store the terms to visit */
1666 ap2 = RepAppl(d0);
1667 f = (Functor)(*ap2);
1668 if (IsExtensionFunctor(f)) {
1669 continue;
1670 }
1671 /* store the terms to visit */
1672 if (tovisit + 1024 >= (CELL **)AuxSp) {
1673 goto aux_overflow;
1674 }
1675#ifdef RATIONAL_TREES
1676 tovisit[0] = pt0;
1677 tovisit[1] = pt0_end;
1678 tovisit[2] = (CELL *)*pt0;
1679 tovisit += 3;
1680 *pt0 = TermNil;
1681#else
1682 if (pt0 < pt0_end) {
1683 tovisit[0] = pt0;
1684 tovisit[1] = pt0_end;
1685 tovisit += 2;
1686 }
1687#endif
1688 d0 = ArityOfFunctor(f);
1689 pt0 = ap2;
1690 pt0_end = ap2 + d0;
1691 }
1692 continue;
1693 }
1694
1695
1696 derefa_body(d0, ptd0, attvars_in_term_unk, attvars_in_term_nvar);
1697 if (IsAttVar(ptd0)) {
1698 /* do or pt2 are unbound */
1699 *ptd0 = TermNil;
1700 /* next make sure noone will see this as a variable again */
1701 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
1702 /* Trail overflow */
1703 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
1704 goto trail_overflow;
1705 }
1706 }
1707 TrailTerm(TR++) = (CELL)ptd0;
1708 /* leave an empty slot to fill in later */
1709 if (HR+1024 > ASP) {
1710 goto global_overflow;
1711 }
1712 HR[1] = AbsPair(HR+2);
1713 HR += 2;
1714 HR[-2] = (CELL)ptd0;
1715 /* store the terms to visit */
1716 if (tovisit + 1024 >= (CELL **)AuxSp) {
1717 goto aux_overflow;
1718 }
1719#ifdef RATIONAL_TREES
1720 tovisit[0] = pt0;
1721 tovisit[1] = pt0_end;
1722 tovisit[2] = (CELL *)*pt0;
1723 tovisit += 3;
1724 *pt0 = TermNil;
1725#else
1726 if (pt0 < pt0_end) {
1727 tovisit[0] = pt0;
1728 tovisit[1] = pt0_end;
1729 tovisit += 2;
1730 }
1731#endif
1732 pt0 = &RepAttVar(ptd0)->Future;
1733 pt0_end = &RepAttVar(ptd0)->Atts;
1734 }
1735 }
1736 /* Do we still have compound terms to visit */
1737 if (tovisit > tovisit0) {
1738#ifdef RATIONAL_TREES
1739 tovisit -= 3;
1740 pt0 = tovisit[0];
1741 pt0_end = tovisit[1];
1742 *pt0 = (CELL)tovisit[2];
1743#else
1744 tovisit -= 2;
1745 pt0 = tovisit[0];
1746 pt0_end = tovisit[1];
1747#endif
1748 goto loop;
1749 }
1750
1751 clean_tr(TR0 PASS_REGS);
1752 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1753 if (HR != InitialH) {
1754 /* close the list */
1755 Term t2 = Deref(inp);
1756 if (IsVarTerm(t2)) {
1757 RESET_VARIABLE(HR-1);
1758 Yap_unify((CELL)(HR-1), t2);
1759 } else {
1760 HR[-1] = t2; /* don't need to trail */
1761 }
1762 return(output);
1763 } else {
1764 return(inp);
1765 }
1766
1767 trail_overflow:
1768#ifdef RATIONAL_TREES
1769 while (tovisit > tovisit0) {
1770 tovisit -= 3;
1771 pt0 = tovisit[0];
1772 *pt0 = (CELL)tovisit[2];
1773 }
1774#endif
1775 LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL;
1776 LOCAL_Error_Size = (TR-TR0)*sizeof(tr_fr_ptr *);
1777 clean_tr(TR0 PASS_REGS);
1778 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1779 HR = InitialH;
1780 return 0L;
1781
1782 aux_overflow:
1783 LOCAL_Error_Size = (tovisit-tovisit0)*sizeof(CELL **);
1784#ifdef RATIONAL_TREES
1785 while (tovisit > tovisit0) {
1786 tovisit -= 3;
1787 pt0 = tovisit[0];
1788 *pt0 = (CELL)tovisit[2];
1789 }
1790#endif
1791 LOCAL_Error_TYPE = RESOURCE_ERROR_AUXILIARY_STACK;
1792 clean_tr(TR0 PASS_REGS);
1793 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1794 HR = InitialH;
1795 return 0L;
1796
1797 global_overflow:
1798#ifdef RATIONAL_TREES
1799 while (tovisit > tovisit0) {
1800 tovisit -= 3;
1801 pt0 = tovisit[0];
1802 *pt0 = (CELL)tovisit[2];
1803 }
1804#endif
1805 clean_tr(TR0 PASS_REGS);
1806 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1807 HR = InitialH;
1808 LOCAL_Error_TYPE = RESOURCE_ERROR_STACK;
1809 LOCAL_Error_Size = (ASP-HR)*sizeof(CELL);
1810 return 0L;
1811
1812}
1813
1814static Int
1815p_term_attvars( USES_REGS1 ) /* variables in term t */
1816{
1817 Term out;
1818
1819 do {
1820 Term t = Deref(ARG1);
1821 if (IsVarTerm(t)) {
1822 out = attvars_in_complex_term(VarOfTerm(t)-1,
1823 VarOfTerm(t)+1, TermNil PASS_REGS);
1824 } else if (IsPrimitiveTerm(t)) {
1825 return Yap_unify(TermNil, ARG2);
1826 } else if (IsPairTerm(t)) {
1827 out = attvars_in_complex_term(RepPair(t)-1,
1828 RepPair(t)+1, TermNil PASS_REGS);
1829 }
1830 else {
1831 Functor f = FunctorOfTerm(t);
1832 out = attvars_in_complex_term(RepAppl(t),
1833 RepAppl(t)+
1834 ArityOfFunctor(f), TermNil PASS_REGS);
1835 }
1836 if (out == 0L) {
1837 if (!expand_vts( 3 PASS_REGS ))
1838 return FALSE;
1839 }
1840 } while (out == 0L);
1841 return Yap_unify(ARG2,out);
1842}
1843#endif
1844
1845static Term vars_within_complex_term(register CELL *pt0, register CELL *pt0_end, Term inp USES_REGS)
1846{
1847
1848 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
1849 register tr_fr_ptr TR0 = TR;
1850 CELL *InitialH = HR;
1851 CELL output = AbsPair(HR);
1852
1853 tovisit0 = tovisit;
1854 while (!IsVarTerm(inp) && IsPairTerm(inp)) {
1855 Term t = HeadOfTerm(inp);
1856 if (IsVarTerm(t)) {
1857 CELL *ptr = VarOfTerm(t);
1858 *ptr = TermFoundVar;
1859 TrailTerm(TR++) = t;
1860 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
1861 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
1862 goto trail_overflow;
1863 }
1864 }
1865 }
1866 inp = TailOfTerm(inp);
1867 }
1868 loop:
1869 while (pt0 < pt0_end) {
1870 register CELL d0;
1871 register CELL *ptd0;
1872 ++ pt0;
1873 ptd0 = pt0;
1874 d0 = *ptd0;
1875 deref_head(d0, vars_within_term_unk);
1876 vars_within_term_nvar:
1877 {
1878 if (IsPairTerm(d0)) {
1879 if (tovisit + 1024 >= (CELL **)AuxSp) {
1880 goto aux_overflow;
1881 }
1882#ifdef RATIONAL_TREES
1883 tovisit[0] = pt0;
1884 tovisit[1] = pt0_end;
1885 tovisit[2] = (CELL *)*pt0;
1886 tovisit += 3;
1887 *pt0 = TermNil;
1888#else
1889 if (pt0 < pt0_end) {
1890 tovisit[0] = pt0;
1891 tovisit[1] = pt0_end;
1892 tovisit += 2;
1893 }
1894#endif
1895 pt0 = RepPair(d0) - 1;
1896 pt0_end = RepPair(d0) + 1;
1897 } else if (IsApplTerm(d0)) {
1898 register Functor f;
1899 register CELL *ap2;
1900 /* store the terms to visit */
1901 ap2 = RepAppl(d0);
1902 f = (Functor)(*ap2);
1903 if (IsExtensionFunctor(f)) {
1904 continue;
1905 }
1906 /* store the terms to visit */
1907 if (tovisit + 1024 >= (CELL **)AuxSp) {
1908 goto aux_overflow;
1909 }
1910#ifdef RATIONAL_TREES
1911 tovisit[0] = pt0;
1912 tovisit[1] = pt0_end;
1913 tovisit[2] = (CELL *)*pt0;
1914 tovisit += 3;
1915 *pt0 = TermNil;
1916#else
1917 if (pt0 < pt0_end) {
1918 tovisit[0] = pt0;
1919 tovisit[1] = pt0_end;
1920 tovisit += 2;
1921 }
1922#endif
1923 d0 = ArityOfFunctor(f);
1924 pt0 = ap2;
1925 pt0_end = ap2 + d0;
1926 } else if (d0 == TermFoundVar) {
1927 /* leave an empty slot to fill in later */
1928 if (HR+1024 > ASP) {
1929 goto global_overflow;
1930 }
1931 HR[1] = AbsPair(HR+2);
1932 HR += 2;
1933 HR[-2] = (CELL)ptd0;
1934 *ptd0 = TermNil;
1935 }
1936 continue;
1937 }
1938
1939 derefa_body(d0, ptd0, vars_within_term_unk, vars_within_term_nvar);
1940 }
1941 /* Do we still have compound terms to visit */
1942 if (tovisit > tovisit0) {
1943#ifdef RATIONAL_TREES
1944 tovisit -= 3;
1945 pt0 = tovisit[0];
1946 pt0_end = tovisit[1];
1947 *pt0 = (CELL)tovisit[2];
1948#else
1949 tovisit -= 2;
1950 pt0 = tovisit[0];
1951 pt0_end = tovisit[1];
1952#endif
1953 goto loop;
1954 }
1955
1956 clean_tr(TR0 PASS_REGS);
1957 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1958 if (HR != InitialH) {
1959 HR[-1] = TermNil;
1960 return output;
1961 } else {
1962 return TermNil;
1963 }
1964
1965 trail_overflow:
1966#ifdef RATIONAL_TREES
1967 while (tovisit > tovisit0) {
1968 tovisit -= 3;
1969 pt0 = tovisit[0];
1970 *pt0 = (CELL)tovisit[2];
1971 }
1972#endif
1973 LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL;
1974 LOCAL_Error_Size = (TR-TR0)*sizeof(tr_fr_ptr *);
1975 clean_tr(TR0 PASS_REGS);
1976 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1977 HR = InitialH;
1978 return 0L;
1979
1980 aux_overflow:
1981 LOCAL_Error_Size = (tovisit-tovisit0)*sizeof(CELL **);
1982#ifdef RATIONAL_TREES
1983 while (tovisit > tovisit0) {
1984 tovisit -= 3;
1985 pt0 = tovisit[0];
1986 *pt0 = (CELL)tovisit[2];
1987 }
1988#endif
1989 LOCAL_Error_TYPE = RESOURCE_ERROR_AUXILIARY_STACK;
1990 clean_tr(TR0 PASS_REGS);
1991 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
1992 HR = InitialH;
1993 return 0L;
1994
1995 global_overflow:
1996#ifdef RATIONAL_TREES
1997 while (tovisit > tovisit0) {
1998 tovisit -= 3;
1999 pt0 = tovisit[0];
2000 *pt0 = (CELL)tovisit[2];
2001 }
2002#endif
2003 clean_tr(TR0 PASS_REGS);
2004 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2005 HR = InitialH;
2006 LOCAL_Error_TYPE = RESOURCE_ERROR_STACK;
2007 LOCAL_Error_Size = (ASP-HR)*sizeof(CELL);
2008 return 0L;
2009
2010}
2011
2012static Int
2013p_variables_within_term( USES_REGS1 ) /* variables within term t */
2014{
2015 Term out;
2016
2017 do {
2018 Term t = Deref(ARG2);
2019 if (IsVarTerm(t)) {
2020 out = vars_within_complex_term(VarOfTerm(t)-1,
2021 VarOfTerm(t), Deref(ARG1) PASS_REGS);
2022
2023 } else if (IsPrimitiveTerm(t))
2024 out = TermNil;
2025 else if (IsPairTerm(t)) {
2026 out = vars_within_complex_term(RepPair(t)-1,
2027 RepPair(t)+1, Deref(ARG1) PASS_REGS);
2028 }
2029 else {
2030 Functor f = FunctorOfTerm(t);
2031 out = vars_within_complex_term(RepAppl(t),
2032 RepAppl(t)+
2033 ArityOfFunctor(f), Deref(ARG1) PASS_REGS);
2034 }
2035 if (out == 0L) {
2036 if (!expand_vts( 3 PASS_REGS ))
2037 return FALSE;
2038 }
2039 } while (out == 0L);
2040 return Yap_unify(ARG3,out);
2041}
2042
2043#if 0
2044static Term free_vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, tr_fr_ptr TR0 USES_REGS)
2045{
2046 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
2047 CELL *InitialH = HR;
2048 *HR++ = MkAtomTerm(AtomDollar);
2049
2050 tovisit0 = tovisit;
2051 loop:
2052 while (pt0 < pt0_end) {
2053 register CELL d0;
2054 register CELL *ptd0;
2055 ++ pt0;
2056 ptd0 = pt0;
2057 d0 = *ptd0;
2058 deref_head(d0, vars_within_term_unk);
2059 vars_within_term_nvar:
2060 {
2061 if (IsPairTerm(d0)) {
2062 if (tovisit + 1024 >= (CELL **)AuxSp) {
2063 goto aux_overflow;
2064 }
2065#ifdef RATIONAL_TREES
2066 tovisit[0] = pt0;
2067 tovisit[1] = pt0_end;
2068 tovisit[2] = (CELL *)*pt0;
2069 tovisit += 3;
2070 *pt0 = TermNil;
2071#else
2072 if (pt0 < pt0_end) {
2073 tovisit[0] = pt0;
2074 tovisit[1] = pt0_end;
2075 tovisit += 2;
2076 }
2077#endif
2078 pt0 = RepPair(d0) - 1;
2079 pt0_end = RepPair(d0) + 1;
2080 } else if (IsApplTerm(d0)) {
2081 register Functor f;
2082 register CELL *ap2;
2083 /* store the terms to visit */
2084 ap2 = RepAppl(d0);
2085 f = (Functor)(*ap2);
2086 if (IsExtensionFunctor(f)) {
2087 continue;
2088 }
2089 /* store the terms to visit */
2090 if (tovisit + 1024 >= (CELL **)AuxSp) {
2091 goto aux_overflow;
2092 }
2093#ifdef RATIONAL_TREES
2094 tovisit[0] = pt0;
2095 tovisit[1] = pt0_end;
2096 tovisit[2] = (CELL *)*pt0;
2097 tovisit += 3;
2098 *pt0 = TermNil;
2099#else
2100 if (pt0 < pt0_end) {
2101 tovisit[0] = pt0;
2102 tovisit[1] = pt0_end;
2103 tovisit += 2;
2104 }
2105#endif
2106 d0 = ArityOfFunctor(f);
2107 pt0 = ap2;
2108 pt0_end = ap2 + d0;
2109 }
2110 continue;
2111 }
2112
2113 derefa_body(d0, ptd0, vars_within_term_unk, vars_within_term_nvar);
2114 /* do or pt2 are unbound */
2115 *ptd0 = TermNil;
2116 /* leave an empty slot to fill in later */
2117 if (HR+1024 > ASP) {
2118 goto global_overflow;
2119 }
2120 HR[0] = (CELL)ptd0;
2121 HR ++;
2122 /* next make sure noone will see this as a variable again */
2123 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
2124 /* Trail overflow */
2125 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
2126 goto trail_overflow;
2127 }
2128 }
2129 TrailTerm(TR++) = (CELL)ptd0;
2130 }
2131 /* Do we still have compound terms to visit */
2132 if (tovisit > tovisit0) {
2133#ifdef RATIONAL_TREES
2134 tovisit -= 3;
2135 pt0 = tovisit[0];
2136 pt0_end = tovisit[1];
2137 *pt0 = (CELL)tovisit[2];
2138#else
2139 tovisit -= 2;
2140 pt0 = tovisit[0];
2141 pt0_end = tovisit[1];
2142#endif
2143 goto loop;
2144 }
2145
2146 clean_tr(TR0 PASS_REGS);
2147 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2148 if (HR != InitialH+1) {
2149 InitialH[0] = (CELL)Yap_MkFunctor(AtomDollar, (HR-InitialH)-1);
2150 return AbsAppl(InitialH);
2151 } else {
2152 return MkAtomTerm(AtomDollar);
2153 }
2154
2155 trail_overflow:
2156#ifdef RATIONAL_TREES
2157 while (tovisit > tovisit0) {
2158 tovisit -= 3;
2159 pt0 = tovisit[0];
2160 *pt0 = (CELL)tovisit[2];
2161 }
2162#endif
2163 LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL;
2164 LOCAL_Error_Size = (TR-TR0)*sizeof(tr_fr_ptr *);
2165 clean_tr(TR0 PASS_REGS);
2166 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2167 HR = InitialH;
2168 return 0L;
2169
2170 aux_overflow:
2171 LOCAL_Error_Size = (tovisit-tovisit0)*sizeof(CELL **);
2172#ifdef RATIONAL_TREES
2173 while (tovisit > tovisit0) {
2174 tovisit -= 3;
2175 pt0 = tovisit[0];
2176 *pt0 = (CELL)tovisit[2];
2177 }
2178#endif
2179 LOCAL_Error_TYPE = RESOURCE_ERROR_AUXILIARY_STACK;
2180 clean_tr(TR0 PASS_REGS);
2181 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2182 HR = InitialH;
2183 return 0L;
2184
2185 global_overflow:
2186#ifdef RATIONAL_TREES
2187 while (tovisit > tovisit0) {
2188 tovisit -= 3;
2189 pt0 = tovisit[0];
2190 *pt0 = (CELL)tovisit[2];
2191 }
2192#endif
2193 clean_tr(TR0 PASS_REGS);
2194 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2195 HR = InitialH;
2196 LOCAL_Error_TYPE = RESOURCE_ERROR_STACK;
2197 LOCAL_Error_Size = (ASP-HR)*sizeof(CELL);
2198 return 0L;
2199
2200}
2201
2202
2203static Term bind_vars_in_complex_term(register CELL *pt0, register CELL *pt0_end, tr_fr_ptr TR0 USES_REGS)
2204{
2205 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
2206 CELL *InitialH = HR;
2207
2208 tovisit0 = tovisit;
2209 loop:
2210 while (pt0 < pt0_end) {
2211 register CELL d0;
2212 register CELL *ptd0;
2213 ++ pt0;
2214 ptd0 = pt0;
2215 d0 = *ptd0;
2216 deref_head(d0, vars_within_term_unk);
2217 vars_within_term_nvar:
2218 {
2219 if (IsPairTerm(d0)) {
2220 if (tovisit + 1024 >= (CELL **)AuxSp) {
2221 goto aux_overflow;
2222 }
2223#ifdef RATIONAL_TREES
2224 tovisit[0] = pt0;
2225 tovisit[1] = pt0_end;
2226 tovisit[2] = (CELL *)*pt0;
2227 tovisit += 3;
2228 *pt0 = TermNil;
2229#else
2230 if (pt0 < pt0_end) {
2231 tovisit[0] = pt0;
2232 tovisit[1] = pt0_end;
2233 tovisit += 2;
2234 }
2235#endif
2236 pt0 = RepPair(d0) - 1;
2237 pt0_end = RepPair(d0) + 1;
2238 } else if (IsApplTerm(d0)) {
2239 register Functor f;
2240 register CELL *ap2;
2241 /* store the terms to visit */
2242 ap2 = RepAppl(d0);
2243 f = (Functor)(*ap2);
2244 if (IsExtensionFunctor(f)) {
2245 continue;
2246 }
2247 /* store the terms to visit */
2248 if (tovisit + 1024 >= (CELL **)AuxSp) {
2249 goto aux_overflow;
2250 }
2251#ifdef RATIONAL_TREES
2252 tovisit[0] = pt0;
2253 tovisit[1] = pt0_end;
2254 tovisit[2] = (CELL *)*pt0;
2255 tovisit += 3;
2256 *pt0 = TermNil;
2257#else
2258 if (pt0 < pt0_end) {
2259 tovisit[0] = pt0;
2260 tovisit[1] = pt0_end;
2261 tovisit += 2;
2262 }
2263#endif
2264 d0 = ArityOfFunctor(f);
2265 pt0 = ap2;
2266 pt0_end = ap2 + d0;
2267 }
2268 continue;
2269 }
2270
2271 derefa_body(d0, ptd0, vars_within_term_unk, vars_within_term_nvar);
2272 /* do or pt2 are unbound */
2273 *ptd0 = TermFoundVar;
2274 /* next make sure noone will see this as a variable again */
2275 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
2276 /* Trail overflow */
2277 if (!Yap_growtrail((TR-TR0)*sizeof(tr_fr_ptr *), TRUE)) {
2278 goto trail_overflow;
2279 }
2280 }
2281 TrailTerm(TR++) = (CELL)ptd0;
2282 }
2283 /* Do we still have compound terms to visit */
2284 if (tovisit > tovisit0) {
2285#ifdef RATIONAL_TREES
2286 tovisit -= 3;
2287 pt0 = tovisit[0];
2288 pt0_end = tovisit[1];
2289 *pt0 = (CELL)tovisit[2];
2290#else
2291 tovisit -= 2;
2292 pt0 = tovisit[0];
2293 pt0_end = tovisit[1];
2294#endif
2295 goto loop;
2296 }
2297
2298 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2299 return TermNil;
2300
2301 trail_overflow:
2302#ifdef RATIONAL_TREES
2303 while (tovisit > tovisit0) {
2304 tovisit -= 3;
2305 pt0 = tovisit[0];
2306 *pt0 = (CELL)tovisit[2];
2307 }
2308#endif
2309 LOCAL_Error_TYPE = RESOURCE_ERROR_TRAIL;
2310 LOCAL_Error_Size = (TR-TR0)*sizeof(tr_fr_ptr *);
2311 clean_tr(TR0 PASS_REGS);
2312 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2313 HR = InitialH;
2314 return 0L;
2315
2316 aux_overflow:
2317 LOCAL_Error_Size = (tovisit-tovisit0)*sizeof(CELL **);
2318#ifdef RATIONAL_TREES
2319 while (tovisit > tovisit0) {
2320 tovisit -= 3;
2321 pt0 = tovisit[0];
2322 *pt0 = (CELL)tovisit[2];
2323 }
2324#endif
2325 LOCAL_Error_TYPE = RESOURCE_ERROR_AUXILIARY_STACK;
2326 clean_tr(TR0 PASS_REGS);
2327 Yap_ReleasePreAllocCodeSpace((ADDR)tovisit0);
2328 HR = InitialH;
2329 return 0L;
2330
2331}
2332
2333#endif
2334
2335
2336static Term non_singletons_in_complex_term(register CELL *pt0, register CELL *pt0_end USES_REGS)
2337{
2338
2339 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
2340 register tr_fr_ptr TR0 = TR;
2341 CELL *InitialH = HR;
2342 CELL output = AbsPair(HR);
2343
2344 tovisit0 = tovisit;
2345 loop:
2346 while (pt0 < pt0_end) {
2347 register CELL d0;
2348 register CELL *ptd0;
2349 ++ pt0;
2350 ptd0 = pt0;
2351 d0 = *ptd0;
2352 deref_head(d0, vars_in_term_unk);
2353 vars_in_term_nvar:
2354 {
2355 if (IsPairTerm(d0)) {
2356 if (tovisit + 1024 >= (CELL **)AuxSp) {
2357 goto aux_overflow;
2358 }
2359#ifdef RATIONAL_TREES
2360 tovisit[0] = pt0;
2361 tovisit[1] = pt0_end;
2362 tovisit[2] = (CELL *)*pt0;
2363 tovisit += 3;
2364 *pt0 = TermNil;
2365#else
2366 if (pt0 < pt0_end) {
2367 tovisit[0] = pt0;
2368 tovisit[1] = pt0_end;
2369 tovisit += 2;
2370 }
2371#endif
2372 pt0 = RepPair(d0) - 1;
2373 pt0_end = RepPair(d0) + 1;
2374 } else if (IsApplTerm(d0)) {
2375 register Functor f;
2376 register CELL *ap2;
2377 /* store the terms to visit */
2378 ap2 = RepAppl(d0);
2379 f = (Functor)(*ap2);
2380
2381 if (IsExtensionFunctor(f)) {
2382
2383 continue;
2384 }
2385 if (tovisit + 1024 >= (CELL **)AuxSp) {
2386 goto aux_overflow;
2387 }
2388#ifdef RATIONAL_TREES
2389 tovisit[0] = pt0;
2390 tovisit[1] = pt0_end;
2391 tovisit[2] = (CELL *)*pt0;
2392 tovisit += 3;
2393 *pt0 = TermNil;
2394#else
2395 /* store the terms to visit */
2396 if (pt0 < pt0_end) {
2397 tovisit[0] = pt0;
2398 tovisit[1] = pt0_end;
2399 tovisit += 2;
2400 }
2401#endif
2402 d0 = ArityOfFunctor(f);
2403 pt0 = ap2;
2404 pt0_end = ap2 + d0;
2405 } else if (d0 == TermFoundVar) {
2406 CELL *pt2 = pt0;
2407 while(IsVarTerm(*pt2))
2408 pt2 = (CELL *)(*pt2);
2409 HR[1] = AbsPair(HR+2);
2410 HR += 2;
2411 HR[-2] = (CELL)pt2;
2412 *pt2 = TermRefoundVar;
2413 }
2414 continue;
2415 }
2416
2417
2418 derefa_body(d0, ptd0, vars_in_term_unk, vars_in_term_nvar);
2419 /* do or pt2 are unbound */
2420 *ptd0 = TermFoundVar;
2421 /* next make sure we can recover the variable again */
2422 TrailTerm(TR++) = (CELL)ptd0;
2423 }
2424 /* Do we still have compound terms to visit */
2425 if (tovisit > tovisit0) {
2426#ifdef RATIONAL_TREES
2427 tovisit -= 3;
2428 pt0 = tovisit[0];
2429 pt0_end = tovisit[1];
2430 *pt0 = (CELL)tovisit[2];
2431#else
2432 tovisit -= 2;
2433 pt0 = tovisit[0];
2434 pt0_end = tovisit[1];
2435#endif
2436 goto loop;
2437 }
2438
2439 clean_tr(TR0 PASS_REGS);
2440 if (HR != InitialH) {
2441 /* close the list */
2442 RESET_VARIABLE(HR-1);
2443 Yap_unify((CELL)(HR-1),ARG2);
2444 return output;
2445 } else {
2446 return ARG2;
2447 }
2448
2449 aux_overflow:
2450#ifdef RATIONAL_TREES
2451 while (tovisit > tovisit0) {
2452 tovisit -= 3;
2453 pt0 = tovisit[0];
2454 *pt0 = (CELL)tovisit[2];
2455 }
2456#endif
2457 clean_tr(TR0 PASS_REGS);
2458 if (HR != InitialH) {
2459 /* close the list */
2460 RESET_VARIABLE(HR-1);
2461 }
2462 return 0L;
2463}
2464
2465static Int
2466p_non_singletons_in_term( USES_REGS1 ) /* non_singletons in term t */
2467{
2468 Term t;
2469 Term out;
2470
2471 while (TRUE) {
2472 t = Deref(ARG1);
2473 if (IsVarTerm(t)) {
2474 out = MkPairTerm(t,ARG2);
2475 } else if (IsPrimitiveTerm(t)) {
2476 out = ARG2;
2477 } else if (IsPairTerm(t)) {
2478 out = non_singletons_in_complex_term(RepPair(t)-1,
2479 RepPair(t)+1 PASS_REGS);
2480 } else {
2481 out = non_singletons_in_complex_term(RepAppl(t),
2482 RepAppl(t)+
2483 ArityOfFunctor(FunctorOfTerm(t)) PASS_REGS);
2484 }
2485 if (out != 0L) {
2486 return Yap_unify(ARG3,out);
2487 } else {
2488 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
2489 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, "overflow in singletons");
2490 return FALSE;
2491 }
2492 }
2493 }
2494}
2495
2496static Int
2497p_ground( USES_REGS1 ) /* ground(+T) */
2498{
2499 return Yap_IsGroundTerm(Deref(ARG1));
2500}
2501
2502static int
2503SizeOfExtension(Term t)
2504{
2505 Functor f = FunctorOfTerm(t);
2506 if (f== FunctorDouble) {
2507 return 2 + sizeof(Float)/sizeof(CELL);
2508 }
2509 if (f== FunctorString) {
2510 return 3 + RepAppl(t)[1];
2511 }
2512 if (f== FunctorLongInt) {
2513 return 2 + sizeof(Float)/sizeof(CELL);
2514 }
2515 if (f== FunctorDBRef) {
2516 return 0;
2517 }
2518 if (f== FunctorBigInt) {
2519 CELL *pt = RepAppl(t)+2;
2520 return 3+sizeof(MP_INT)+(((MP_INT *)(pt))->_mp_alloc*sizeof(mp_limb_t));
2521 }
2522 return 0;
2523}
2524
2525
2526static Int sz_ground_complex_term(register CELL *pt0, register CELL *pt0_end, int ground USES_REGS)
2527{
2528
2529 register CELL **tovisit0, **tovisit = (CELL **)Yap_PreAllocCodeSpace();
2530 Int sz = 0;
2531
2532 tovisit0 = tovisit;
2533 loop:
2534 while (pt0 < pt0_end) {
2535 register CELL d0;
2536 register CELL *ptd0;
2537
2538 ++pt0;
2539 ptd0 = pt0;
2540 d0 = *ptd0;
2541 deref_head(d0, vars_in_term_unk);
2542 vars_in_term_nvar:
2543 {
2544 if (IsPairTerm(d0)) {
2545 sz += 2;
2546 if (tovisit + 1024 >= (CELL **)AuxSp) {
2547 goto aux_overflow;
2548 }
2549#ifdef RATIONAL_TREES
2550 tovisit[0] = pt0;
2551 tovisit[1] = pt0_end;
2552 tovisit[2] = (CELL *)*pt0;
2553 tovisit += 3;
2554 *pt0 = TermNil;
2555#else
2556 if (pt0 < pt0_end) {
2557 tovisit[0] = pt0;
2558 tovisit[1] = pt0_end;
2559 tovisit += 2;
2560 }
2561#endif
2562 pt0 = RepPair(d0) - 1;
2563 pt0_end = RepPair(d0) + 1;
2564 } else if (IsApplTerm(d0)) {
2565 register Functor f;
2566 register CELL *ap2;
2567 /* store the terms to visit */
2568 ap2 = RepAppl(d0);
2569 f = (Functor)(*ap2);
2570
2571 if (IsExtensionFunctor(f)) {
2572 sz += SizeOfExtension(d0);
2573 continue;
2574 }
2575 if (tovisit + 1024 >= (CELL **)AuxSp) {
2576 goto aux_overflow;
2577 }
2578#ifdef RATIONAL_TREES
2579 tovisit[0] = pt0;
2580 tovisit[1] = pt0_end;
2581 tovisit[2] = (CELL *)*pt0;
2582 tovisit += 3;
2583 *pt0 = TermNil;
2584#else
2585 /* store the terms to visit */
2586 if (pt0 < pt0_end) {
2587 tovisit[0] = pt0;
2588 tovisit[1] = pt0_end;
2589 tovisit += 2;
2590 }
2591#endif
2592 d0 = ArityOfFunctor(f);
2593 sz += (1+d0);
2594 pt0 = ap2;
2595 pt0_end = ap2 + d0;
2596 }
2597 continue;
2598 }
2599
2600
2601 derefa_body(d0, ptd0, vars_in_term_unk, vars_in_term_nvar);
2602 if (!ground)
2603 continue;
2604#ifdef RATIONAL_TREES
2605 while (tovisit > tovisit0) {
2606 tovisit -= 3;
2607 pt0 = tovisit[0];
2608 pt0_end = tovisit[1];
2609 *pt0 = (CELL)tovisit[2];
2610 }
2611#endif
2612 return 0;
2613 }
2614 /* Do we still have compound terms to visit */
2615 if (tovisit > tovisit0) {
2616#ifdef RATIONAL_TREES
2617 tovisit -= 3;
2618 pt0 = tovisit[0];
2619 pt0_end = tovisit[1];
2620 *pt0 = (CELL)tovisit[2];
2621#else
2622 tovisit -= 2;
2623 pt0 = tovisit[0];
2624 pt0_end = tovisit[1];
2625#endif
2626 goto loop;
2627 }
2628 return sz;
2629
2630 aux_overflow:
2631 /* unwind stack */
2632#ifdef RATIONAL_TREES
2633 while (tovisit > tovisit0) {
2634 tovisit -= 3;
2635 pt0 = tovisit[0];
2636 *pt0 = (CELL)tovisit[2];
2637 }
2638#endif
2639 return -1;
2640}
2641
2642int
2643Yap_SizeGroundTerm(Term t, int ground)
2644{
2645 CACHE_REGS
2646 if (IsVarTerm(t)) {
2647 if (!ground)
2648 return 1;
2649 return 0;
2650 } else if (IsPrimitiveTerm(t)) {
2651 return 1;
2652 } else if (IsPairTerm(t)) {
2653 int sz = sz_ground_complex_term(RepPair(t)-1, RepPair(t)+1, ground PASS_REGS);
2654 if (sz <= 0)
2655 return sz;
2656 return sz+2;
2657} else {
2658 int sz = 0;
2659 Functor fun = FunctorOfTerm(t);
2660
2661 if (IsExtensionFunctor(fun))
2662 return 1+ SizeOfExtension(t);
2663
2664 sz = sz_ground_complex_term(RepAppl(t),
2665 RepAppl(t)+
2666 ArityOfFunctor(fun),
2667 ground PASS_REGS);
2668 if (sz <= 0)
2669 return sz;
2670 return 1+ArityOfFunctor(fun)+sz;
2671 }
2672}
2673
2674/* The code for TermHash was originally contributed by Gertjen Van Noor */
2675
2676/* This code with max_depth == -1 will loop for infinite trees */
2677
2678
2679//-----------------------------------------------------------------------------
2680// MurmurHash2, by Austin Appleby
2681
2682// Note - This code makes a few assumptions about how your machine behaves -
2683
2684// 1. We can read a 4-byte value from any address without crashing
2685// 2. sizeof(int) == 4
2686
2687// And it has a few limitations -
2688
2689// 1. It will not work incrementally.
2690// 2. It will not produce the same results on little-endian and big-endian
2691// machines.
2692
2693static unsigned int
2694MurmurHashNeutral2 ( const void * key, int len, unsigned int seed )
2695{
2696 const unsigned int m = 0x5bd1e995;
2697 const int r = 24;
2698
2699 unsigned int h = seed ^ len;
2700
2701 const unsigned char * data = (const unsigned char *)key;
2702
2703 while(len >= 4)
2704 {
2705 unsigned int k;
2706
2707 k = data[0];
2708 k |= data[1] << 8;
2709 k |= data[2] << 16;
2710 k |= data[3] << 24;
2711
2712 k *= m;
2713 k ^= k >> r;
2714 k *= m;
2715
2716 h *= m;
2717 h ^= k;
2718
2719 data += 4;
2720 len -= 4;
2721 }
2722
2723 switch(len)
2724 {
2725 case 3: h ^= data[2] << 16;
2726 case 2: h ^= data[1] << 8;
2727 case 1: h ^= data[0];
2728 h *= m;
2729 };
2730
2731 h ^= h >> 13;
2732 h *= m;
2733 h ^= h >> 15;
2734
2735 return h;
2736}
2737
2738static CELL *
2739addAtomToHash(CELL *st, Atom at)
2740{
2741 unsigned int len;
2742
2743 char *c = RepAtom(at)->StrOfAE;
2744 int ulen = strlen(c);
2745 /* fix hashing over empty atom */
2746 if (!ulen) {
2747 return st;
2748 }
2749 if (ulen % CellSize == 0) {
2750 len = ulen/CellSize;
2751 } else {
2752 len = ulen/CellSize;
2753 len++;
2754 }
2755 st[len-1] = 0L;
2756 strncpy((char *)st, c, ulen);
2757 return st+len;
2758}
2759
2760typedef struct visited {
2761 CELL *start;
2762 CELL *end;
2763 CELL old;
2764 UInt vdepth;
2765} visited_t;
2766
2767static CELL *
2768hash_complex_term(register CELL *pt0,
2769 register CELL *pt0_end,
2770 Int depth,
2771 CELL *st,
2772 int variant USES_REGS)
2773{
2774 register visited_t *tovisit0, *tovisit = (visited_t *)Yap_PreAllocCodeSpace();
2775
2776 tovisit0 = tovisit;
2777 loop:
2778 while (pt0 < pt0_end) {
2779 register CELL d0;
2780 register CELL *ptd0;
2781 ++ pt0;
2782 ptd0 = pt0;
2783 d0 = *ptd0;
2784 deref_head(d0, hash_complex_unk);
2785 hash_complex_nvar:
2786 {
2787 if (st + 1024 >= ASP) {
2788 goto global_overflow;
2789 }
2790 if (IsAtomOrIntTerm(d0)) {
2791 if (d0 != TermFoundVar) {
2792 if (IsAtomTerm(d0)) {
2793 st = addAtomToHash(st, AtomOfTerm(d0));
2794 } else {
2795 *st++ = IntOfTerm(d0);
2796 }
2797 }
2798 continue;
2799 } else if (IsPairTerm(d0)) {
2800 st = addAtomToHash(st, AtomDot);
2801 if (depth == 1)
2802 continue;
2803 if (tovisit + 256 >= (visited_t *)AuxSp) {
2804 goto aux_overflow;
2805 }
2806 tovisit->start = pt0;
2807 tovisit->end = pt0_end;
2808 tovisit->old = *pt0;
2809 tovisit->vdepth = depth;
2810 tovisit++;
2811 depth--;
2812 *pt0 = TermFoundVar;
2813 pt0 = RepPair(d0) - 1;
2814 pt0_end = RepPair(d0) + 1;
2815 continue;
2816 } else if (IsApplTerm(d0)) {
2817 register Functor f;
2818 register CELL *ap2;
2819 /* store the terms to visit */
2820 ap2 = RepAppl(d0);
2821 f = (Functor)(*ap2);
2822
2823 if (IsExtensionFunctor(f)) {
2824 CELL fc = (CELL)f;
2825
2826 switch(fc) {
2827
2828 case (CELL)FunctorDBRef:
2829 *st++ = fc;
2830 break;
2831 case (CELL)FunctorLongInt:
2832 *st++ = LongIntOfTerm(d0);
2833 break;
2834 case (CELL)FunctorString:
2835 memcpy(st, RepAppl(d0), (3+RepAppl(d0)[1])*sizeof(CELL));
2836 st += 3+RepAppl(d0)[1];
2837 break;
2838#ifdef USE_GMP
2839 case (CELL)FunctorBigInt:
2840 {
2841 CELL *pt = RepAppl(d0);
2842 Int sz =
2843 sizeof(MP_INT)+1+
2844 (((MP_INT *)(pt+2))->_mp_alloc*sizeof(mp_limb_t));
2845
2846 if (st + (1024 + sz/CellSize) >= ASP) {
2847 goto global_overflow;
2848 }
2849 /* then the actual number */
2850 memcpy((void *)(st+1), (void *)(pt+1), sz);
2851 st = st+sz/CellSize;
2852 }
2853 break;
2854#endif
2855 case (CELL)FunctorDouble:
2856 {
2857 CELL *pt = RepAppl(d0);
2858 *st++ = pt[1];
2859#if SIZEOF_DOUBLE == 2*SIZEOF_INT_P
2860 *st++ = pt[2];
2861#endif
2862 break;
2863 }
2864 }
2865 continue;
2866 }
2867 st = addAtomToHash(st, NameOfFunctor(f));
2868 if (depth == 1)
2869 continue;
2870 if (tovisit + 1024 >= (visited_t *)AuxSp) {
2871 goto aux_overflow;
2872 }
2873 tovisit->start = pt0;
2874 tovisit->end = pt0_end;
2875 tovisit->old = *pt0;
2876 tovisit->vdepth = depth;
2877 tovisit++;
2878 depth--;
2879 *pt0 = TermFoundVar;
2880 d0 = ArityOfFunctor(f);
2881 pt0 = ap2;
2882 pt0_end = ap2 + d0;
2883 }
2884 continue;
2885 }
2886
2887
2888 deref_body(d0, ptd0, hash_complex_unk, hash_complex_nvar);
2889 if (!variant)
2890 return NULL;
2891 else
2892 continue;
2893 }
2894 /* Do we still have compound terms to visit */
2895 if (tovisit > tovisit0) {
2896 tovisit--;
2897 pt0 = tovisit->start;
2898 pt0_end = tovisit->end;
2899 *pt0 = tovisit->old;
2900 depth = tovisit->vdepth;
2901 goto loop;
2902 }
2903 return st;
2904
2905 aux_overflow:
2906 /* unwind stack */
2907 while (tovisit > tovisit0) {
2908 tovisit --;
2909 pt0 = tovisit->start;
2910 *pt0 = tovisit->old;
2911 }
2912 return (CELL *)-1;
2913
2914 global_overflow:
2915 /* unwind stack */
2916 while (tovisit > tovisit0) {
2917 tovisit --;
2918 pt0 = tovisit->start;
2919 *pt0 = tovisit->old;
2920 }
2921 return (CELL *) -2;
2922}
2923
2924Int
2925Yap_TermHash(Term t, Int size, Int depth, int variant)
2926{
2927 CACHE_REGS
2928 unsigned int i1;
2929 Term t1 = Deref(t);
2930
2931 while (TRUE) {
2932 CELL *ar = hash_complex_term(&t1-1, &t1, depth, HR, FALSE PASS_REGS);
2933 if (ar == (CELL *)-1) {
2934 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
2935 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, "overflow in term_hash");
2936 return FALSE;
2937 }
2938 t1 = Deref(ARG1);
2939 } else if(ar == (CELL *)-2) {
2940 if (!Yap_dogc(PASS_REGS1)) {
2941 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in term_hash");
2942 return FALSE;
2943 }
2944 t1 = Deref(ARG1);
2945 } else if (ar == NULL) {
2946 return FALSE;
2947 } else {
2948 i1 = MurmurHashNeutral2((const void *)HR, CellSize*(ar-HR),0x1a3be34a);
2949 break;
2950 }
2951 }
2952 /* got the seed and hash from SWI-Prolog */
2953 return i1 % size;
2954}
2955
2956static Int
2957p_term_hash( USES_REGS1 )
2958{
2959 unsigned int i1;
2960 Term t1 = Deref(ARG1);
2961 Term t2 = Deref(ARG2);
2962 Term t3 = Deref(ARG3);
2963 Term result;
2964 Int size, depth;
2965
2966 if (IsVarTerm(t2)) {
2967 Yap_ThrowError(INSTANTIATION_ERROR,t2,"term_hash/4");
2968 return(FALSE);
2969 }
2970 if (!IsIntegerTerm(t2)) {
2971 Yap_ThrowError(TYPE_ERROR_INTEGER,t2,"term_hash/4");
2972 return(FALSE);
2973 }
2974 depth = IntegerOfTerm(t2);
2975 if (depth == 0) {
2976 if (IsVarTerm(t1)) return(TRUE);
2977 return(Yap_unify(ARG4,MkIntTerm(0)));
2978 }
2979 if (IsVarTerm(t3)) {
2980 Yap_ThrowError(INSTANTIATION_ERROR,t3,"term_hash/4");
2981 return(FALSE);
2982 }
2983 if (!IsIntegerTerm(t3)) {
2984 Yap_ThrowError(TYPE_ERROR_INTEGER,t3,"term_hash/4");
2985 return(FALSE);
2986 }
2987 size = IntegerOfTerm(t3);
2988 while (TRUE) {
2989 CELL *ar = hash_complex_term(&t1-1, &t1, depth, HR, FALSE PASS_REGS);
2990 if (ar == (CELL *)-1) {
2991 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
2992 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, "overflow in term_hash");
2993 return FALSE;
2994 }
2995 t1 = Deref(ARG1);
2996 } else if(ar == (CELL *)-2) {
2997 if (!Yap_dogc(PASS_REGS1)) {
2998 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in term_hash");
2999 return FALSE;
3000 }
3001 t1 = Deref(ARG1);
3002 } else if (ar == NULL) {
3003 return FALSE;
3004 } else {
3005 i1 = MurmurHashNeutral2((const void *)HR, CellSize*(ar-HR),0x1a3be34a);
3006 break;
3007 }
3008 }
3009 /* got the seed and hash from SWI-Prolog */
3010 result = MkIntegerTerm(i1 % size);
3011 return Yap_unify(ARG4,result);
3012}
3013
3014static Int
3015p_instantiated_term_hash( USES_REGS1 )
3016{
3017 unsigned int i1;
3018 Term t1 = Deref(ARG1);
3019 Term t2 = Deref(ARG2);
3020 Term t3 = Deref(ARG3);
3021 Term result;
3022 Int size, depth;
3023
3024 if (IsVarTerm(t2)) {
3025 Yap_ThrowError(INSTANTIATION_ERROR,t2,"term_hash/4");
3026 return(FALSE);
3027 }
3028 if (!IsIntegerTerm(t2)) {
3029 Yap_ThrowError(TYPE_ERROR_INTEGER,t2,"term_hash/4");
3030 return(FALSE);
3031 }
3032 depth = IntegerOfTerm(t2);
3033 if (depth == 0) {
3034 if (IsVarTerm(t1)) return(TRUE);
3035 return(Yap_unify(ARG4,MkIntTerm(0)));
3036 }
3037 if (IsVarTerm(t3)) {
3038 Yap_ThrowError(INSTANTIATION_ERROR,t3,"term_hash/4");
3039 return(FALSE);
3040 }
3041 if (!IsIntegerTerm(t3)) {
3042 Yap_ThrowError(TYPE_ERROR_INTEGER,t3,"term_hash/4");
3043 return(FALSE);
3044 }
3045 size = IntegerOfTerm(t3);
3046 while (TRUE) {
3047 CELL *ar = hash_complex_term(&t1-1, &t1, depth, HR, TRUE PASS_REGS);
3048 if (ar == (CELL *)-1) {
3049 if (!Yap_ExpandPreAllocCodeSpace(0, NULL, TRUE)) {
3050 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, ARG1, "overflow in term_hash");
3051 return FALSE;
3052 }
3053 t1 = Deref(ARG1);
3054 } else if(ar == (CELL *)-2) {
3055 if (!Yap_dogc(PASS_REGS1)) {
3056 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in term_hash");
3057 return FALSE;
3058 }
3059 t1 = Deref(ARG1);
3060 } else if (ar == NULL) {
3061 return FALSE;
3062 } else {
3063 i1 = MurmurHashNeutral2((const void *)HR, CellSize*(ar-HR),0x1a3be34a);
3064 break;
3065 }
3066 }
3067 /* got the seed and hash from SWI-Prolog */
3068 result = MkIntegerTerm(i1 % size);
3069 return Yap_unify(ARG4,result);
3070}
3071
3072static int variant_complex(register CELL *pt0, register CELL *pt0_end, register
3073 CELL *pt1 USES_REGS)
3074{
3075 tr_fr_ptr OLDTR = TR;
3076 register CELL **tovisit = (CELL **)ASP;
3077 /* make sure that unification always forces trailing */
3078 HBREG = HR;
3079
3080
3081 loop:
3082 while (pt0 < pt0_end) {
3083 register CELL d0, d1;
3084 ++ pt0;
3085 ++ pt1;
3086 d0 = Derefa(pt0);
3087 d1 = Derefa(pt1);
3088 if (IsVarTerm(d0)) {
3089 if (IsVarTerm(d1)) {
3090 CELL *pt0 = VarOfTerm(d0);
3091 CELL *pt1 = VarOfTerm(d1);
3092 if (pt0 >= HBREG || pt1 >= HBREG) {
3093 /* one of the variables has been found before */
3094 if (VarOfTerm(d0)+1 == VarOfTerm(d1)) continue;
3095 goto fail;
3096 } else {
3097 /* two new occurrences of the same variable */
3098 Term n0 = MkVarTerm(), n1 = MkVarTerm();
3099 Bind_Global(VarOfTerm(d0), n0);
3100 Bind_Global(VarOfTerm(d1), n1);
3101 }
3102 continue;
3103 } else {
3104 goto fail;
3105 }
3106 } else if (IsVarTerm(d1)) {
3107 goto fail;
3108 } else {
3109 if (d0 == d1) continue;
3110 else if (IsAtomOrIntTerm(d0)) {
3111 goto fail;
3112 } else if (IsPairTerm(d0)) {
3113 if (!IsPairTerm(d1)) {
3114 goto fail;
3115 }
3116#ifdef RATIONAL_TREES
3117 /* now link the two structures so that no one else will */
3118 /* come here */
3119 tovisit -= 4;
3120 if ((CELL *)tovisit < HR+1024)
3121 goto out_of_stack;
3122 tovisit[0] = pt0;
3123 tovisit[1] = pt0_end;
3124 tovisit[2] = pt1;
3125 tovisit[3] = (CELL *)*pt0;
3126 *pt0 = d1;
3127#else
3128 /* store the terms to visit */
3129 if (pt0 < pt0_end) {
3130 tovisit -= 3;
3131 if ((CELL *)tovisit < HR+1024)
3132 goto out_of_stack;
3133 tovisit[0] = pt0;
3134 tovisit[1] = pt0_end;
3135 tovisit[2] = pt1;
3136 }
3137#endif
3138 pt0 = RepPair(d0) - 1;
3139 pt0_end = RepPair(d0) + 1;
3140 pt1 = RepPair(d1) - 1;
3141 continue;
3142 } else if (IsApplTerm(d0)) {
3143 register Functor f;
3144 register CELL *ap2, *ap3;
3145 if (!IsApplTerm(d1)) {
3146 goto fail;
3147 } else {
3148 /* store the terms to visit */
3149 Functor f2;
3150 ap2 = RepAppl(d0);
3151 ap3 = RepAppl(d1);
3152 f = (Functor)(*ap2);
3153 f2 = (Functor)(*ap3);
3154 if (f != f2)
3155 goto fail;
3156 if (IsExtensionFunctor(f)) {
3157 if (!unify_extension(f, d0, ap2, d1))
3158 goto fail;
3159 continue;
3160 }
3161#ifdef RATIONAL_TREES
3162 /* now link the two structures so that no one else will */
3163 /* come here */
3164 tovisit -= 4;
3165 if ((CELL *)tovisit < HR+1024)
3166 goto out_of_stack;
3167 tovisit[0] = pt0;
3168 tovisit[1] = pt0_end;
3169 tovisit[2] = pt1;
3170 tovisit[3] = (CELL *)*pt0;
3171 *pt0 = d1;
3172#else
3173 /* store the terms to visit */
3174 if (pt0 < pt0_end) {
3175 tovisit -= 3;
3176 if ((CELL *)tovisit < HR+1024)
3177 goto out_of_stack;
3178 tovisit[0] = pt0;
3179 tovisit[1] = pt0_end;
3180 tovisit[2] = pt1;
3181 }
3182#endif
3183 d0 = ArityOfFunctor(f);
3184 pt0 = ap2;
3185 pt0_end = ap2 + d0;
3186 pt1 = ap3;
3187 continue;
3188 }
3189 }
3190 }
3191 }
3192 /* Do we still have compound terms to visit */
3193 if (tovisit < (CELL **)ASP) {
3194#ifdef RATIONAL_TREES
3195 pt0 = tovisit[0];
3196 pt0_end = tovisit[1];
3197 pt1 = tovisit[2];
3198 *pt0 = (CELL)tovisit[3];
3199 tovisit += 4;
3200#else
3201 pt0 = tovisit[0];
3202 pt0_end = tovisit[1];
3203 pt1 = tovisit[2];
3204 tovisit += 3;
3205#endif
3206 goto loop;
3207 }
3208
3209 HR = HBREG;
3210 /* untrail all bindings made by variant */
3211 while (TR != (tr_fr_ptr)OLDTR) {
3212 CELL *pt1 = (CELL *) TrailTerm(--TR);
3213 RESET_VARIABLE(pt1);
3214 }
3215 HBREG = B->cp_h;
3216 return TRUE;
3217
3218 out_of_stack:
3219 HR = HBREG;
3220 /* untrail all bindings made by variant */
3221#ifdef RATIONAL_TREES
3222 while (tovisit < (CELL **)ASP) {
3223 pt0 = tovisit[0];
3224 pt0_end = tovisit[1];
3225 pt1 = tovisit[2];
3226 *pt0 = (CELL)tovisit[3];
3227 tovisit += 4;
3228 }
3229#endif
3230 while (TR != (tr_fr_ptr)OLDTR) {
3231 CELL *pt1 = (CELL *) TrailTerm(--TR);
3232 RESET_VARIABLE(pt1);
3233 }
3234 HBREG = B->cp_h;
3235 return -1;
3236
3237
3238 fail:
3239 /* failure */
3240 HR = HBREG;
3241#ifdef RATIONAL_TREES
3242 while (tovisit < (CELL **)ASP) {
3243 pt0 = tovisit[0];
3244 pt0_end = tovisit[1];
3245 pt1 = tovisit[2];
3246 *pt0 = (CELL)tovisit[3];
3247 tovisit += 4;
3248 }
3249#endif
3250 /* untrail all bindings made by variant */
3251 while (TR != (tr_fr_ptr)OLDTR) {
3252 CELL *pt1 = (CELL *) TrailTerm(--TR);
3253 RESET_VARIABLE(pt1);
3254 }
3255 HBREG = B->cp_h;
3256 return FALSE;
3257}
3258
3259static bool
3260is_variant(Term t1, Term t2, int parity USES_REGS)
3261{
3262 int out;
3263
3264 if (t1 == t2)
3265 return true;
3266 if (IsVarTerm(t1)) {
3267 if (IsVarTerm(t2))
3268 return true;
3269 return false;
3270 } else if (IsVarTerm(t2))
3271 return false;
3272 if (IsAtomOrIntTerm(t1)) {
3273 return(t1 == t2);
3274 }
3275 if (IsPairTerm(t1)) {
3276 if (IsPairTerm(t2)) {
3277 out = variant_complex(RepPair(t1)-1,
3278 RepPair(t1)+1,
3279 RepPair(t2)-1 PASS_REGS);
3280 if (out < 0) goto error;
3281 return out != 0;
3282 }
3283 else return false;
3284 }
3285 if (!IsApplTerm(t2)) {
3286 return false;
3287 } else {
3288 Functor f1 = FunctorOfTerm(t1);
3289
3290 if (f1 != FunctorOfTerm(t2)) return(FALSE);
3291 if (IsExtensionFunctor(f1)) {
3292 return(unify_extension(f1, t1, RepAppl(t1), t2));
3293 }
3294 out = variant_complex(RepAppl(t1),
3295 RepAppl(t1)+ArityOfFunctor(f1),
3296 RepAppl(t2) PASS_REGS);
3297 if (out < 0) goto error;
3298 return out != 0;
3299 }
3300 error:
3301 if (out == -1) {
3302 if (!Yap_dogc(PASS_REGS1)) {
3303 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in variant");
3304 return FALSE;
3305 }
3306 return is_variant(t1, t2, parity PASS_REGS);
3307 }
3308 return false;
3309}
3310
3311bool
3312Yap_Variant(Term t1, Term t2)
3313{
3314 CACHE_REGS
3315 return is_variant(t1, t2, 0 PASS_REGS);
3316}
3317
3318static Int
3319p_variant( USES_REGS1 ) /* variant terms t1 and t2 */
3320{
3321 return is_variant(Deref(ARG1), Deref(ARG2), 2 PASS_REGS);
3322}
3323
3324
3325static int subsumes_complex(register CELL *pt0, register CELL *pt0_end, register
3326 CELL *pt1 USES_REGS)
3327{
3328 register CELL **tovisit = (CELL **)ASP;
3329 tr_fr_ptr OLDTR = TR;
3330 UInt write_mode = TRUE;
3331
3332
3333 HBREG = HR;
3334 loop:
3335 while (pt0 < pt0_end) {
3336 register CELL d0, d1;
3337 Int our_write_mode = write_mode;
3338
3339 ++ pt0;
3340 ++ pt1;
3341 /* this is a version of Derefa that checks whether we are trying to
3342 do something evil */
3343 {
3344 CELL *npt0 = pt0;
3345
3346 restart_d0:
3347 if (npt0 >= HBREG) {
3348 our_write_mode = FALSE;
3349 }
3350 d0 = *npt0;
3351 if (IsVarTerm(d0) &&
3352 d0 != (CELL)npt0
3353 ) {
3354 npt0 = (CELL *)d0;
3355 goto restart_d0;
3356 }
3357 }
3358 {
3359 CELL *npt1 = pt1;
3360
3361 restart_d1:
3362 d1 = *npt1;
3363 if (IsVarTerm(d1)
3364 && d1 != (CELL)npt1
3365 ) {
3366 /* never dereference through a variable from the left-side */
3367 if (npt1 >= HBREG) {
3368 goto fail;
3369 } else {
3370 npt1 = (CELL *)d1;
3371 goto restart_d1;
3372 }
3373 }
3374 }
3375 if (IsVarTerm(d0)) {
3376 if (our_write_mode) {
3377 /* generate a new binding */
3378 CELL *pt0 = VarOfTerm(d0);
3379 Term new = MkVarTerm();
3380
3381 Bind_and_Trail(pt0, new);
3382 if (d0 != d1) { /* avoid loops */
3383 Bind_and_Trail(VarOfTerm(new), d1);
3384 if (Yap_rational_tree_loop(VarOfTerm(new)-1,VarOfTerm(new),(CELL **)AuxSp,(CELL **)AuxBase))
3385 goto fail;
3386 }
3387 } else {
3388 if (d0 == d1) continue;
3389 goto fail;
3390 }
3391 continue;
3392 } else if (IsVarTerm(d1)) {
3393 goto fail;
3394 } else {
3395 if (d0 == d1) continue;
3396 else if (IsAtomOrIntTerm(d0)) {
3397 goto fail;
3398 } else if (IsPairTerm(d0)) {
3399 if (!IsPairTerm(d1)) {
3400 goto fail;
3401 }
3402#ifdef RATIONAL_TREES
3403 /* now link the two structures so that no one else will */
3404 /* come here */
3405 tovisit -= 5;
3406 tovisit[0] = pt0;
3407 tovisit[1] = pt0_end;
3408 tovisit[2] = pt1;
3409 tovisit[3] = (CELL *)*pt0;
3410 tovisit[4] = (CELL *)write_mode;
3411 *pt0 = d1;
3412#else
3413 /* store the terms to visit */
3414 if (pt0 < pt0_end) {
3415 tovisit -= 4;
3416 tovisit[0] = pt0;
3417 tovisit[1] = pt0_end;
3418 tovisit[2] = pt1;
3419 tovisit[3] = (CELL *)write_mode;
3420 }
3421#endif
3422 write_mode = our_write_mode;
3423 pt0 = RepPair(d0) - 1;
3424 pt0_end = RepPair(d0) + 1;
3425 pt1 = RepPair(d1) - 1;
3426 continue;
3427 } else if (IsApplTerm(d0)) {
3428 register Functor f;
3429 register CELL *ap2, *ap3;
3430 if (!IsApplTerm(d1)) {
3431 goto fail;
3432 } else {
3433 /* store the terms to visit */
3434 Functor f2;
3435 ap2 = RepAppl(d0);
3436 ap3 = RepAppl(d1);
3437 f = (Functor)(*ap2);
3438 f2 = (Functor)(*ap3);
3439 if (f != f2)
3440 goto fail;
3441 if (IsExtensionFunctor(f)) {
3442 if (!unify_extension(f, d0, ap2, d1))
3443 goto fail;
3444 continue;
3445 }
3446#ifdef RATIONAL_TREES
3447 /* now link the two structures so that no one else will */
3448 /* come here */
3449 tovisit -= 5;
3450 tovisit[0] = pt0;
3451 tovisit[1] = pt0_end;
3452 tovisit[2] = pt1;
3453 tovisit[3] = (CELL *)*pt0;
3454 tovisit[4] = (CELL *)write_mode;
3455 *pt0 = d1;
3456#else
3457 /* store the terms to visit */
3458 if (pt0 < pt0_end) {
3459 tovisit -= 4;
3460 tovisit[0] = pt0;
3461 tovisit[1] = pt0_end;
3462 tovisit[2] = pt1;
3463 tovisit[3] = (CELL *)write_mode;
3464 }
3465#endif
3466 write_mode = our_write_mode;
3467 d0 = ArityOfFunctor(f);
3468 pt0 = ap2;
3469 pt0_end = ap2 + d0;
3470 pt1 = ap3;
3471 continue;
3472 }
3473 }
3474 }
3475 }
3476 /* Do we still have compound terms to visit */
3477 if (tovisit < (CELL **)ASP) {
3478#ifdef RATIONAL_TREES
3479 pt0 = tovisit[0];
3480 pt0_end = tovisit[1];
3481 pt1 = tovisit[2];
3482 *pt0 = (CELL)tovisit[3];
3483 write_mode = (Int)tovisit[ 4];
3484 tovisit += 5;
3485#else
3486 pt0 = tovisit[0];
3487 pt0_end = tovisit[1];
3488 pt1 = tovisit[2];
3489 write_mode = (UInt)tovisit[3];
3490 tovisit += 4;
3491#endif
3492 goto loop;
3493 }
3494
3495 HR = HBREG;
3496 /* get rid of intermediate variables */
3497 while (TR != OLDTR) {
3498 /* cell we bound */
3499 CELL *pt1 = (CELL *) TrailTerm(--TR);
3500 RESET_VARIABLE(pt1);
3501 }
3502 HBREG = B->cp_h;
3503 return TRUE;
3504
3505 fail:
3506 HR = HBREG;
3507#ifdef RATIONAL_TREES
3508 while (tovisit < (CELL **)ASP) {
3509 pt0 = tovisit[0];
3510 pt0_end = tovisit[1];
3511 pt1 = tovisit[2];
3512 *pt0 = (CELL)tovisit[3];
3513 tovisit += 5;
3514 }
3515#endif
3516 /* untrail all bindings made by variant */
3517 while (TR != (tr_fr_ptr)OLDTR) {
3518 CELL *pt1 = (CELL *) TrailTerm(--TR);
3519 RESET_VARIABLE(pt1);
3520 }
3521 HBREG = B->cp_h;
3522 return FALSE;
3523}
3524
3525static Int
3526p_subsumes( USES_REGS1 ) /* subsumes terms t1 and t2 */
3527{
3528 Term t1 = Deref(ARG1);
3529 Term t2 = Deref(ARG2);
3530
3531 if (t1 == t2)
3532 return (TRUE);
3533 if (IsVarTerm(t1)) {
3534 YapBind(VarOfTerm(t1), t2);
3535 if (Yap_rational_tree_loop(VarOfTerm(t1)-1,VarOfTerm(t1),(CELL **)AuxSp,(CELL **)AuxBase))
3536 return FALSE;
3537
3538 RESET_VARIABLE(VarOfTerm(t1));
3539 return TRUE;
3540 } else if (IsVarTerm(t2))
3541 return(FALSE);
3542 if (IsAtomOrIntTerm(t1)) {
3543 return(t1 == t2);
3544 }
3545 if (IsPairTerm(t1)) {
3546 if (IsPairTerm(t2)) {
3547 return(subsumes_complex(RepPair(t1)-1,
3548 RepPair(t1)+1,
3549 RepPair(t2)-1 PASS_REGS));
3550 }
3551 else return (FALSE);
3552 } else {
3553 Functor f1;
3554
3555 if (!IsApplTerm(t2)) return(FALSE);
3556 f1 = FunctorOfTerm(t1);
3557 if (f1 != FunctorOfTerm(t2))
3558 return(FALSE);
3559 if (IsExtensionFunctor(f1)) {
3560 return(unify_extension(f1, t1, RepAppl(t1), t2));
3561 }
3562 return(subsumes_complex(RepAppl(t1),
3563 RepAppl(t1)+ArityOfFunctor(f1),
3564 RepAppl(t2) PASS_REGS));
3565 }
3566}
3567
3568
3569static int term_subsumer_complex(register CELL *pt0, register CELL *pt0_end, register
3570 CELL *pt1, CELL *npt USES_REGS)
3571{
3572 register CELL **tovisit = (CELL **)ASP;
3573 tr_fr_ptr OLDTR = TR;
3574 int out;
3575 CELL *bindings = NULL, *tbindings = NULL;
3576 HB = HR;
3577
3578 loop:
3579 while (pt0 < pt0_end) {
3580 register CELL d0, d1;
3581
3582 ++ pt0;
3583 ++ pt1;
3584 d0 = Derefa(pt0);
3585 d1 = Derefa(pt1);
3586 if (d0 == d1) {
3587 *npt++ = d0;
3588 continue;
3589 } else if (IsVarTerm(d0)) {
3590 CELL *match, *omatch = NULL;
3591
3592 match = VarOfTerm(d0);
3593 if (match >= HB) {
3594 while (match >= HB) {
3595 /* chained to a sequence */
3596 if (Yap_eq(d1, match[1]) ) {
3597 *npt++ = match[2];
3598 break;
3599 }
3600 omatch = match;
3601 match = (CELL *)match[3];
3602 }
3603 /* found a match */
3604 if (match >= HB)
3605 continue;
3606 /* could not find a match, add to end of chain */
3607 RESET_VARIABLE(HR); /* key */
3608 HR[1] = d1; /* comparison value */
3609 HR[2] = (CELL)npt; /* new value */
3610 HR[3] = (CELL)match; /* end of chain points back to first cell */
3611 omatch[3] = (CELL)HR;
3612 HR+=4;
3613 RESET_VARIABLE(npt);
3614 npt++;
3615 continue;
3616 }
3617 if (TR > (tr_fr_ptr)LOCAL_TrailTop - 256) {
3618 goto trail_overflow;
3619 }
3620 RESET_VARIABLE(HR);
3621 HR[1] = d1;
3622 HR[2] = (CELL)npt;
3623 HR[3] = d0;
3624 YapBind(VarOfTerm(d0), (CELL)HR);
3625 HR+=4;
3626 RESET_VARIABLE(npt);
3627 npt++;
3628 continue;
3629 } else if (IsPairTerm(d0) && IsPairTerm(d1)) {
3630 CELL *match = bindings;
3631
3632 while (match) {
3633 if (match[0] == d0 && match[1] == d1) {
3634 *npt++ = match[2];
3635 break;
3636 }
3637 match = (CELL *)match[3];
3638 }
3639 if (match) {
3640 continue;
3641 }
3642 if (bindings) {
3643 *tbindings = (CELL)HR;
3644 } else {
3645 bindings = HR;
3646 }
3647 HR[0] = d0;
3648 HR[1] = d1;
3649 HR[2] = AbsPair(HR+4);
3650 HR[3] = (CELL)NULL;
3651 tbindings = HR+3;
3652 HR+=4;
3653 *npt++ = AbsPair(HR);
3654#ifdef RATIONAL_TREES
3655 /* now link the two structures so that no one else will */
3656 /* come here */
3657 tovisit -= 5;
3658 tovisit[0] = pt0;
3659 tovisit[1] = pt0_end;
3660 tovisit[2] = pt1;
3661 tovisit[3] = tbindings;
3662 tovisit[4] = npt;
3663#else
3664 /* store the terms to visit */
3665 if (pt0 < pt0_end) {
3666 tovisit -= 4;
3667 tovisit[0] = pt0;
3668 tovisit[1] = pt0_end;
3669 tovisit[2] = pt1;
3670 tovisit[3] = npt;
3671 }
3672#endif
3673 pt0 = RepPair(d0) - 1;
3674 pt0_end = RepPair(d0) + 1;
3675 pt1 = RepPair(d1) - 1;
3676 npt = HR;
3677 HR += 2;
3678 if (HR > (CELL *)tovisit -1024)
3679 goto stack_overflow;
3680 continue;
3681 } else if (IsApplTerm(d0) && IsApplTerm(d1)) {
3682 CELL *ap2 = RepAppl(d0);
3683 CELL *ap3 = RepAppl(d1);
3684 Functor f = (Functor)(*ap2);
3685 Functor f2 = (Functor)(*ap3);
3686 if (f == f2) {
3687 CELL *match = bindings;
3688
3689 if (IsExtensionFunctor(f)) {
3690 if (unify_extension(f, d0, ap2, d1)) {
3691 *npt++ = d0;
3692 continue;
3693 }
3694 }
3695 while (match) {
3696 if (match[0] == d0 && match[1] == d1) {
3697 *npt++ = match[2];
3698 break;
3699 }
3700 match = (CELL *)match[3];
3701 }
3702 if (match) {
3703 continue;
3704 }
3705 if (bindings) {
3706 *tbindings = (CELL)HR;
3707 } else {
3708 bindings = HR;
3709 }
3710 HR[0] = d0;
3711 HR[1] = d1;
3712 HR[2] = AbsAppl(HR+4);
3713 HR[3] = (CELL)NULL;
3714 tbindings = HR+3;
3715 HR+=4;
3716 *npt++ = AbsAppl(HR);
3717#ifdef RATIONAL_TREES
3718 /* now link the two structures so that no one else will */
3719 /* come here */
3720 tovisit -= 5;
3721 tovisit[0] = pt0;
3722 tovisit[1] = pt0_end;
3723 tovisit[2] = pt1;
3724 tovisit[3] = tbindings;
3725 tovisit[4] = npt;
3726#else
3727 /* store the terms to visit */
3728 if (pt0 < pt0_end) {
3729 tovisit -= 4;
3730 tovisit[0] = pt0;
3731 tovisit[1] = pt0_end;
3732 tovisit[2] = pt1;
3733 tovisit[3] = npt;
3734 }
3735#endif
3736 d0 = ArityOfFunctor(f);
3737 pt0 = ap2;
3738 pt0_end = ap2 + d0;
3739 pt1 = ap3;
3740 npt = HR;
3741 *npt++ = (CELL)f;
3742 HR += d0;
3743 if (HR > (CELL *)tovisit -1024)
3744 goto stack_overflow;
3745 continue;
3746 }
3747 }
3748 RESET_VARIABLE(npt);
3749 npt++;
3750 }
3751 /* Do we still have compound terms to visit */
3752 if (tovisit < (CELL **)ASP) {
3753#ifdef RATIONAL_TREES
3754 pt0 = tovisit[0];
3755 pt0_end = tovisit[1];
3756 pt1 = tovisit[2];
3757 tbindings = tovisit[3];
3758 npt = tovisit[ 4];
3759 if (!tbindings) {
3760 bindings = NULL;
3761 }
3762 tovisit += 5;
3763#else
3764 pt0 = tovisit[0];
3765 pt0_end = tovisit[1];
3766 pt1 = tovisit[2];
3767 npt = tovisit[3];
3768 tovisit += 4;
3769#endif
3770 goto loop;
3771 }
3772 out = 1;
3773
3774 complete:
3775 /* get rid of intermediate variables */
3776 while (TR != OLDTR) {
3777 CELL *pt1 = (CELL *) TrailTerm(--TR);
3778 RESET_VARIABLE(pt1);
3779 }
3780 HBREG = B->cp_h;
3781 return out;
3782
3783 stack_overflow:
3784 out = -1;
3785 goto complete;
3786
3787 trail_overflow:
3788 out = -2;
3789 goto complete;
3790
3791}
3792
3793static Int
3794p_term_subsumer( USES_REGS1 ) /* term_subsumer terms t1 and t2 */
3795{
3796 int out = 0;
3797
3798 while (out != 1) {
3799 Term t1 = Deref(ARG1);
3800 Term t2 = Deref(ARG2);
3801 CELL *oldH = HR;
3802
3803 if (t1 == t2)
3804 return Yap_unify(ARG3,t1);
3805 if (IsPairTerm(t1) && IsPairTerm(t2)) {
3806 Term tf = AbsAppl(HR);
3807 HR += 2;
3808 HB = HR;
3809 if ((out = term_subsumer_complex(RepPair(t1)-1,
3810 RepPair(t1)+1,
3811 RepPair(t2)-1, HR-2 PASS_REGS)) > 0) {
3812 HB = B->cp_h;
3813 return Yap_unify(ARG3,tf);
3814 }
3815 } else if (IsApplTerm(t1) && IsApplTerm(t2)) {
3816 Functor f1;
3817
3818 if ((f1 = FunctorOfTerm(t1)) == FunctorOfTerm(t2)) {
3819 if (IsExtensionFunctor(f1)) {
3820 if (unify_extension(f1, t1, RepAppl(t1), t2)) {
3821 return Yap_unify(ARG3,t1);
3822 }
3823 } else {
3824 Term tf = AbsAppl(HR);
3825 UInt ar = ArityOfFunctor(f1);
3826 HR[0] = (CELL)f1;
3827 HR += 1+ar;
3828 HB = HR;
3829 if ((out = term_subsumer_complex(RepAppl(t1),
3830 RepAppl(t1)+ArityOfFunctor(f1),
3831 RepAppl(t2), HR-ar PASS_REGS)) > 0) {
3832 HB = B->cp_h;
3833 return Yap_unify(ARG3,tf);
3834 }
3835 }
3836 }
3837 }
3838 HB = B->cp_h;
3839 if (out == 0) {
3840 return Yap_unify(ARG3, MkVarTerm());
3841 } else {
3842 HR = oldH;
3843 if (out == -1) {
3844 if (!Yap_dogc(PASS_REGS1)) {
3845 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "in term_subsumer");
3846 return FALSE;
3847 }
3848 } else {
3849 /* Trail overflow */
3850 if (!Yap_growtrail(0, FALSE)) {
3851 Yap_ThrowError(RESOURCE_ERROR_TRAIL, TermNil, "in term_subsumer");
3852 return FALSE;
3853 }
3854 }
3855 }
3856 }
3857 return FALSE;
3858}
3859
3860#ifdef DEBUG
3861static Int
3862p_force_trail_expansion( USES_REGS1 )
3863{
3864 Int i = IntOfTerm(Deref(ARG1))*1024, j = 0;
3865 tr_fr_ptr OTR = TR;
3866
3867 for (j = 0; j < i; j++) {
3868 TrailTerm(TR) = 0;
3869 TR++;
3870 }
3871 TR = OTR;
3872
3873 return(TRUE);
3874}
3875
3876static Int
3877camacho_dum( USES_REGS1 )
3878{
3879 Term t1, t2;
3880 int max = 3;
3881
3882 /* build output list */
3883
3884 t1 = TermNil;
3885 t2 = MkPairTerm(MkIntegerTerm(max), t1);
3886
3887 return(Yap_unify(t2, ARG1));
3888}
3889
3890
3891
3892#endif /* DEBUG */
3893
3894bool
3895Yap_IsListTerm(Term t)
3896{
3897 Term *tailp;
3898 Yap_SkipList(&t, &tailp);
3899 return *tailp == TermNil;
3900}
3901
3902static Int
3903p_is_list( USES_REGS1 )
3904{
3905 return Yap_IsListTerm(Deref(ARG1));
3906}
3907
3908bool
3909Yap_IsListOrPartialListTerm(Term t)
3910{
3911 Term *tailp, tail;
3912 Yap_SkipList(&t, &tailp);
3913 tail = *tailp;
3914 return tail == TermNil || IsVarTerm(tail);
3915}
3916
3917static Int
3918p_is_list_or_partial_list( USES_REGS1 )
3919{
3920 return Yap_IsListOrPartialListTerm(Deref(ARG1));
3921}
3922
3923static int
3924unnumber_complex_term(CELL *pt0, CELL *pt0_end, CELL *ptf, CELL *HLow, int share USES_REGS)
3925{
3926
3927 struct cp_frame *tovisit0, *tovisit = (struct cp_frame *)Yap_PreAllocCodeSpace();
3928 CELL *HB0 = HB;
3929 tr_fr_ptr TR0 = TR;
3930 int ground = share;
3931 Int max = -1;
3932
3933 HB = HLow;
3934 tovisit0 = tovisit;
3935 loop:
3936 while (pt0 < pt0_end) {
3937 register CELL d0;
3938 register CELL *ptd0;
3939 ++ pt0;
3940 ptd0 = pt0;
3941 d0 = *ptd0;
3942 deref_head(d0, unnumber_term_unk);
3943 unnumber_term_nvar:
3944 {
3945 if (IsPairTerm(d0)) {
3946 CELL *ap2 = RepPair(d0);
3947 if (ap2 >= HB && ap2 < HR) {
3948 /* If this is newer than the current term, just reuse */
3949 *ptf++ = d0;
3950 continue;
3951 }
3952 *ptf = AbsPair(HR);
3953 ptf++;
3954#ifdef RATIONAL_TREES
3955 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
3956 goto heap_overflow;
3957 }
3958 tovisit->pt0 = pt0;
3959 tovisit->pt0_end = pt0_end;
3960 tovisit->ptf = ptf;
3961 tovisit->oldv = *pt0;
3962 tovisit->ground = ground;
3963 /* fool the system into thinking we had a variable there */
3964 *pt0 = AbsPair(HR);
3965 tovisit ++;
3966#else
3967 if (pt0 < pt0_end) {
3968 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
3969 goto heap_overflow;
3970 }
3971 tovisit->pt0 = pt0;
3972 tovisit->pt0_end = pt0_end;
3973 tovisit->ptf = ptf;
3974 tovisit->ground = ground;
3975 tovisit ++;
3976 }
3977#endif
3978 ground = share;
3979 pt0 = ap2 - 1;
3980 pt0_end = ap2 + 1;
3981 ptf = HR;
3982 HR += 2;
3983 if (HR > ASP - 2048) {
3984 goto overflow;
3985 }
3986 } else if (IsApplTerm(d0)) {
3987 register Functor f;
3988 register CELL *ap2;
3989 /* store the terms to visit */
3990 ap2 = RepAppl(d0);
3991 if (ap2 >= HB && ap2 <= HR) {
3992 /* If this is newer than the current term, just reuse */
3993 *ptf++ = d0;
3994 continue;
3995 }
3996 f = (Functor)(*ap2);
3997
3998 if (IsExtensionFunctor(f)) {
3999 *ptf++ = d0; /* you can just unnumber other extensions. */
4000 continue;
4001 }
4002 if (f == FunctorDollarVar) {
4003 Int id = IntegerOfTerm(ap2[1]);
4004 ground = FALSE;
4005 if (id < -1) {
4006 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, "unnumber vars cannot cope with VAR(-%d)", id);
4007 return 0L;
4008 }
4009 if (id <= max) {
4010 if (ASP-(max+1) <= HR) {
4011 goto overflow;
4012 }
4013 /* we found this before? */
4014 if (ASP[-id-1])
4015 *ptf++ = ASP[-id-1];
4016 else {
4017 RESET_VARIABLE(ptf);
4018 ASP[-id-1] = (CELL)ptf;
4019 ptf++;
4020 }
4021 continue;
4022 }
4023 /* alloc more space */
4024 if (ASP-(id+1) <= HR) {
4025 goto overflow;
4026 }
4027 while (id > max) {
4028 ASP[-(id+1)] = 0L;
4029 max++;
4030 }
4031 /* new variable */
4032 RESET_VARIABLE(ptf);
4033 ASP[-(id+1)] = (CELL)ptf;
4034 ptf++;
4035 continue;
4036 }
4037 *ptf = AbsAppl(HR);
4038 ptf++;
4039 /* store the terms to visit */
4040#ifdef RATIONAL_TREES
4041 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
4042 goto heap_overflow;
4043 }
4044 tovisit->pt0 = pt0;
4045 tovisit->pt0_end = pt0_end;
4046 tovisit->ptf = ptf;
4047 tovisit->oldv = *pt0;
4048 tovisit->ground = ground;
4049 /* fool the system into thinking we had a variable there */
4050 *pt0 = AbsAppl(HR);
4051 tovisit ++;
4052#else
4053 if (pt0 < pt0_end) {
4054 if (tovisit+1 >= (struct cp_frame *)AuxSp) {
4055 goto heap_overflow;
4056 }
4057 tovisit->pt0 = pt0;
4058 tovisit->pt0_end = pt0_end;
4059 tovisit->ptf = ptf;
4060 tovisit->ground = ground;
4061 tovisit ++;
4062 }
4063#endif
4064 ground = (f != FunctorMutable) && share;
4065 d0 = ArityOfFunctor(f);
4066 pt0 = ap2;
4067 pt0_end = ap2 + d0;
4068 /* store the functor for the new term */
4069 HR[0] = (CELL)f;
4070 ptf = HR+1;
4071 HR += 1+d0;
4072 if (HR > ASP - 2048) {
4073 goto overflow;
4074 }
4075 } else {
4076 /* just unnumber atoms or integers */
4077 *ptf++ = d0;
4078 }
4079 continue;
4080 }
4081
4082 derefa_body(d0, ptd0, unnumber_term_unk, unnumber_term_nvar);
4083 /* this should never happen ? */
4084 ground = FALSE;
4085 *ptf++ = (CELL) ptd0;
4086 }
4087 /* Do we still have compound terms to visit */
4088 if (tovisit > tovisit0) {
4089 tovisit --;
4090 if (ground) {
4091 CELL old = tovisit->oldv;
4092 CELL *newp = tovisit->ptf-1;
4093 CELL new = *newp;
4094
4095 *newp = old;
4096 if (IsApplTerm(new))
4097 HR = RepAppl(new);
4098 else
4099 HR = RepPair(new);
4100 }
4101 pt0 = tovisit->pt0;
4102 pt0_end = tovisit->pt0_end;
4103 ptf = tovisit->ptf;
4104#ifdef RATIONAL_TREES
4105 *pt0 = tovisit->oldv;
4106#endif
4107 ground = (ground && tovisit->ground);
4108 goto loop;
4109 }
4110
4111 /* restore our nice, friendly, term to its original state */
4112 clean_dirty_tr(TR0 PASS_REGS);
4113 HB = HB0;
4114 return ground;
4115
4116 overflow:
4117 /* oops, we're in trouble */
4118 HR = HLow;
4119 /* we've done it */
4120 /* restore our nice, friendly, term to its original state */
4121 HB = HB0;
4122#ifdef RATIONAL_TREES
4123 while (tovisit > tovisit0) {
4124 tovisit --;
4125 pt0 = tovisit->pt0;
4126 pt0_end = tovisit->pt0_end;
4127 ptf = tovisit->ptf;
4128 *pt0 = tovisit->oldv;
4129 }
4130#endif
4131 reset_trail(TR0);
4132 /* follow chain of multi-assigned variables */
4133 return -1;
4134
4135 heap_overflow:
4136 /* oops, we're in trouble */
4137 HR = HLow;
4138 /* we've done it */
4139 /* restore our nice, friendly, term to its original state */
4140 HB = HB0;
4141#ifdef RATIONAL_TREES
4142 while (tovisit > tovisit0) {
4143 tovisit --;
4144 pt0 = tovisit->pt0;
4145 pt0_end = tovisit->pt0_end;
4146 ptf = tovisit->pt0_end;
4147 *pt0 = tovisit->oldv;
4148 }
4149#endif
4150 reset_trail(TR0);
4151 LOCAL_Error_Size = (ADDR)AuxSp-(ADDR)tovisit0;
4152 return -3;
4153}
4154
4155
4156static Term
4157UnnumberTerm(Term inp, UInt arity, int share USES_REGS) {
4158 Term t = Deref(inp);
4159 tr_fr_ptr TR0 = TR;
4160
4161 if (IsVarTerm(t)) {
4162 return inp;
4163 } else if (IsPrimitiveTerm(t)) {
4164 return t;
4165 } else if (IsPairTerm(t)) {
4166 Term tf;
4167 CELL *ap;
4168 CELL *Hi;
4169
4170 restart_list:
4171 ap = RepPair(t);
4172 Hi = HR;
4173 tf = AbsPair(HR);
4174 HR += 2;
4175 {
4176 int res;
4177 if ((res = unnumber_complex_term(ap-1, ap+1, Hi, Hi, share PASS_REGS)) < 0) {
4178 HR = Hi;
4179 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
4180 return FALSE;
4181 goto restart_list;
4182 } else if (res) {
4183 HR = Hi;
4184 return t;
4185 }
4186 }
4187 return tf;
4188 } else {
4189 Functor f = FunctorOfTerm(t);
4190 Term tf;
4191 CELL *HB0;
4192 CELL *ap;
4193
4194 restart_appl:
4195 f = FunctorOfTerm(t);
4196 HB0 = HR;
4197 ap = RepAppl(t);
4198 tf = AbsAppl(HR);
4199 HR[0] = (CELL)f;
4200 HR += 1+ArityOfFunctor(f);
4201 if (HR > ASP-128) {
4202 HR = HB0;
4203 if ((t = handle_cp_overflow(-1, TR0, arity, t))== 0L)
4204 return FALSE;
4205 goto restart_appl;
4206 } else {
4207 int res;
4208
4209 if ((res = unnumber_complex_term(ap, ap+ArityOfFunctor(f), HB0+1, HB0, share PASS_REGS)) < 0) {
4210 HR = HB0;
4211 if ((t = handle_cp_overflow(res, TR0, arity, t))== 0L)
4212 return FALSE;
4213 goto restart_appl;
4214 } else if (res && FunctorOfTerm(t) != FunctorMutable) {
4215 HR = HB0;
4216 return t;
4217 }
4218 }
4219 return tf;
4220 }
4221}
4222
4223/*
4224Term
4225Yap_UnNumberTerm(Term inp, int share) {
4226 CACHE_REGS
4227 return UnnumberTerm(inp, 0, share PASS_REGS);
4228}
4229*/
4230
4231static Int
4232unnumbervars( USES_REGS1 ) {
4233 /* this should be a standard Prolog term, so we allow sharing? */
4234 return Yap_unify(UnnumberTerm(ARG1, 2, FALSE PASS_REGS), ARG2);
4235}
4236
4237
4238Int
4239Yap_SkipList(Term *l, Term **tailp)
4240{
4241 Int length = 0;
4242 Term *s; /* slow */
4243 Term v; /* temporary */
4244
4245 do_derefa(v,l,derefa_unk,derefa_nonvar);
4246 s = l;
4247
4248 if ( IsPairTerm(*l) )
4249 { intptr_t power = 1, lam = 0;
4250 do
4251 { if ( power == lam )
4252 { s = l;
4253 power *= 2;
4254 lam = 0;
4255 }
4256 lam++;
4257 length++;
4258 l = RepPair(*l)+1;
4259 do_derefa(v,l,derefa2_unk,derefa2_nonvar);
4260 } while ( *l != *s && IsPairTerm(*l) );
4261 }
4262 *tailp = l;
4263
4264 return length;
4265}
4266
4267
4268static Int
4269p_skip_list( USES_REGS1 ) {
4270 Term *tail;
4271 Int len = Yap_SkipList(XREGS+2, &tail);
4272
4273 return Yap_unify(MkIntegerTerm(len), ARG1) &&
4274 Yap_unify(*tail, ARG3);
4275}
4276
4277static Int
4278p_skip_list4( USES_REGS1 ) {
4279 Term *tail;
4280 Int len, len1 = -1;
4281 Term t2 = Deref(ARG2), t;
4282
4283 if (!IsVarTerm(t2)) {
4284 if (!IsIntegerTerm(t2)) {
4285 Yap_ThrowError(TYPE_ERROR_INTEGER, t2, "length/2");
4286 return FALSE;
4287 }
4288 if ((len1 = IntegerOfTerm(t2)) < 0) {
4289 Yap_ThrowError(DOMAIN_ERROR_NOT_LESS_THAN_ZERO, t2, "length/2");
4290 return FALSE;
4291 }
4292 }
4293 /* we need len here */
4294 len = Yap_SkipList(XREGS+1, &tail);
4295 t = *tail;
4296 /* don't set M0 if full list, just check M */
4297 if (t == TermNil) {
4298 if (len1 >= 0) { /* ARG2 was bound */
4299 return
4300 len1 == len &&
4301 Yap_unify(t, ARG4);
4302 } else {
4303 return Yap_unify_constant(ARG4, TermNil) &&
4304 Yap_unify_constant(ARG2, MkIntegerTerm(len));
4305 }
4306 }
4307 return Yap_unify(MkIntegerTerm(len), ARG3) &&
4308 Yap_unify(t, ARG4);
4309}
4310
4311static Int
4312p_free_arguments( USES_REGS1 )
4313{
4314 Term t = Deref(ARG1);
4315 if (IsVarTerm(t))
4316 return FALSE;
4317 if (IsAtomTerm(t) || IsIntTerm(t))
4318 return TRUE;
4319 if (IsPairTerm(t)) {
4320 Term th = HeadOfTerm(t);
4321 Term tl = TailOfTerm(t);
4322 return IsVarTerm(th) && IsVarTerm(tl) && th != tl;
4323 } else {
4324 Functor f = FunctorOfTerm(t);
4325 UInt i, ar;
4326 Int ret = TRUE;
4327
4328 if (IsExtensionFunctor(f))
4329 return TRUE;
4330 ar = ArityOfFunctor(f);
4331 for (i = 1 ; i <= ar; i++) {
4332 Term ta = ArgOfTerm(i, t);
4333 Int j;
4334
4335 ret = IsVarTerm(ta);
4336 if (!ret) break;
4337 /* stupid quadractic algorithm, but needs no testing for overflows */
4338 for (j = 1 ; j < i; j++) {
4339 ret = ArgOfTerm(j, t) != ta;
4340 if (!ret) break;
4341 }
4342 if (!ret) break;
4343 }
4344 return ret;
4345 }
4346}
4347
4348static Int
4349p_freshen_variables( USES_REGS1 )
4350{
4351 Term t = Deref(ARG1);
4352 Functor f = FunctorOfTerm(t);
4353 UInt arity = ArityOfFunctor(f), i;
4354 Term tn = Yap_MkNewApplTerm(f, arity);
4355 CELL *src = RepAppl(t)+1;
4356 CELL *targ = RepAppl(tn)+1;
4357 for (i=0; i< arity; i++) {
4358 RESET_VARIABLE(targ);
4359 *VarOfTerm(*src) = (CELL)targ;
4360 targ++;
4361 src++;
4362 }
4363 return TRUE;
4364}
4365
4366static Int
4367p_reset_variables( USES_REGS1 )
4368{
4369 Term t = Deref(ARG1);
4370 Functor f = FunctorOfTerm(t);
4371 UInt arity = ArityOfFunctor(f), i;
4372 CELL *src = RepAppl(t)+1;
4373
4374 for (i=0; i< arity; i++) {
4375 RESET_VARIABLE(VarOfTerm(*src));
4376 src++;
4377 }
4378 return TRUE;
4379}
4380
4381void Yap_InitUtilCPreds(void)
4382{
4383 CACHE_REGS
4384 Term cm = CurrentModule;
4385 // Yap_InitCPred("copy_term", 2, p_copy_term, 0);
4386 //Yap_InitCPred("duplicate_term", 2, p_duplicate_term, 0);
4387 //Yap_InitCPred("copy_term_nat", 2, p_copy_term_no_delays, 0);
4388 Yap_InitCPred("_ground", 1, p_ground, SafePredFlag);
4396 Yap_InitCPred("$_variables_in_term", 3, p_variables_in_term, 0);
4397 //Yap_InitCPred("$free_variables_in_term", 3, p_free_variables_in_term, 0);
4398 Yap_InitCPred("$non_singletons_in_term", 3, p_non_singletons_in_term, 0);
4399 //Yap_InitCPred("term_variables", 2, p_term_variables, 0);
4410 //Yap_InitCPred("term_variables", 3, p_term_variables3, 0);
4411 //Yap_InitCPred("term_attvars", 2, p_term_attvars, 0);
4421 Yap_InitCPred("is_list", 1, p_is_list, SafePredFlag|TestPredFlag);
4422 Yap_InitCPred("$is_list_or_partial_list", 1, p_is_list_or_partial_list, SafePredFlag|TestPredFlag);
4423 Yap_InitCPred("rational_term_to_tree", 4, p_break_rational, 0);
4435 Yap_InitCPred("term_factorized", 3, p_break_rational3, 0);
4443 Yap_InitCPred("=@=", 2, p_variant, 0);
4444 // Yap_InitCPred("numbervars", 3, p_numbervars, 0);
4445 Yap_InitCPred("unnumbervars", 2, unnumbervars, 0);
4446 Yap_InitCPred("varnumbers", 2, unnumbervars, 0);
4447 /* use this carefully */
4448 Yap_InitCPred("$skip_list", 3, p_skip_list, SafePredFlag|TestPredFlag);
4449 Yap_InitCPred("$skip_list", 4, p_skip_list4, SafePredFlag|TestPredFlag);
4450 Yap_InitCPred("$free_arguments", 1, p_free_arguments, TestPredFlag);
4451 CurrentModule = TERMS_MODULE;
4452 // Yap_InitCPred("variable_in_term", 2, p_var_in_term, 0);
4453 Yap_InitCPred("term_hash", 4, p_term_hash, 0);
4454 Yap_InitCPred("instantiated_term_hash", 4, p_instantiated_term_hash, 0);
4455 Yap_InitCPred("variant", 2, p_variant, 0);
4456 Yap_InitCPred("subsumes", 2, p_subsumes, 0);
4457 Yap_InitCPred("term_subsumer", 3, p_term_subsumer, 0);
4458 Yap_InitCPred("variables_within_term", 3, p_variables_within_term, 0);
4459 //Yap_InitCPred("new_variables_in_term", 3, p_new_variables_in_term, 0);
4460 Yap_InitCPred("export_term", 3, p_export_term, 0);
4461 Yap_InitCPred("kill_exported_term", 1, p_kill_exported_term, SafePredFlag);
4462 Yap_InitCPred("import_term", 2, p_import_term, 0);
4463 Yap_InitCPred("freshen_variables", 1, p_freshen_variables, 0);
4464 Yap_InitCPred("reset_variables", 1, p_reset_variables, 0);
4465 CurrentModule = cm;
4466#ifdef DEBUG
4467 Yap_InitCPred("$force_trail_expansion", 1, p_force_trail_expansion, SafePredFlag);
4468 Yap_InitCPred("dum", 1, camacho_dum, SafePredFlag);
4469#endif
4470}
4471
A matrix.
Definition: matrix.c:68
Definition: engine.c:83