YAP 7.1.0
terms.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 * Last rev: 4/03/88
12 *
13 * mods:
14 * comments: new utility predicates for YAP *
15 * *
16 *************************************************************************/
17
18#ifndef TERMS_C
19#define TERMS_C 1
20
21//#define DEB_D0(S) printf("%s %s: d0=%lx ptd0=%p *ptd0=%lx\n",S,d0, ptd0,
34#include "absmi.h"
35
36#include "YapHeap.h"
37
38#include "heapgc.h"
39
40#include "attvar.h"
41#include "clause.h"
42#include "yapio.h"
43#ifdef HAVE_STRING_H
44#include "string.h"
45#endif
46
47#define DEB_DOOBOUT(d0) \
48 // (fprintf(stderr, ">>>>>>> %s ", __FUNCTION__), Yap_DebugPlWriteln(d0))
49#define DEB_DOOBIN(d0) //(fprintf(stderr,"<<<<<<<<<<<<<<<<<<<<<<< %s:%d\n", __FUNCTION__, __LINE__)/*, Yap_DebugPlWriteln(d0))*/)
50#define DEB_DOOB(S,sp) // fprintf(stderr, "%s %s:%d %ld \n ", S,__FUNCTION__, __LINE__, sp->pt- sp->pt0)
51
52/*#define err, "%s %ld %p->%p=%lx ", s, st->pt - st->pt0, pt0, ptd0, d0), */
53/* Yap_DebugPlWriteln(d0)) */
54
55#define push_sub_term(A,B,C,D,E) \
56 if (A->pt + 2 >= A->max && realloc_stack(stt) == 0) { \
57 A->err = RESOURCE_ERROR_AUXILIARY_STACK;\
58 continue;\
59 }\
60 push_sub_term__(A,B,C,D,E);
61#define pop_sub_term(A,B,C) ( DEB_DOOB("-",A) pop_sub_term__(A,B,C))
62static inline bool push_sub_term__(Ystack_t *sp, CELL d0, CELL *pt0, CELL *b,
63 CELL *e) {
64 copy_frame *pt = sp->pt;
65 pt->pt0 = b;
66 pt->pt0_end = e;
67 pt->oldv = d0;
68 pt->oldp = pt0;
69 sp->pt++;
70 return true;
71}
72
73static inline bool pop_sub_term__(Ystack_t *sp, CELL **b, CELL **e) {
74 copy_frame *pt = --(sp->pt);
75 if (pt < sp->pt0) {
76 return false;
77 }
78 if (pt->oldp != NULL && *pt->oldp)
79 pt->oldp[0] = pt->oldv;
80 if (b)
81 *b = pt->pt0;
82 if (e)
83 *e = pt->pt0_end;
84 return true;
85}
86
87#define RESET_TERM_VISITOR_0() \
88 if (stt->err){ Term* pt0,*pt0_end;\
89 while ((pop_sub_term(stt, &pt0, &pt0_end))){} ; \
90 stt->arenap= NULL; \
91 stt->bindp = NULL; \
92 HR = stt->hlow; \
93 t = term_error_handler(stt->bindp,t,stt); \
94stt->err = 0; \
95 }
96
97#define RESET_TERM_VISITOR_1(v,v0) \
98 if (stt->err){ Term* pt0,*pt0_end;\
99 while ((pop_sub_term(stt, &pt0, &pt0_end))){} ; \
100 stt->arenap= NULL; \
101 stt->bindp = NULL; \
102 HR = stt->hlow;\
103yhandle_t yv = Yap_InitHandle(v0); \
104 t = term_error_handler(stt->bindp,t,stt); \
105stt->err = 0;\
106v = v0=Yap_PopHandle(yv); \
107 }
108#endif
109
110
111#define RESET_TERM_VISITOR_3(first,tail,tail0,end) \
112 if (stt->err){ Term* pt0,*pt0_end;\
113 while ((pop_sub_term(stt, &pt0, &pt0_end))){}; \
114 stt->arenap= NULL; \
115 stt->bindp = NULL; \
116 HR = stt->hlow; \
117 yhandle_t yv = Yap_InitHandle(tail0);\
118 t = term_error_handler(stt->bindp,t,stt); \
119 tail0 = Yap_PopHandle(yv);\
120 tail = tail0;\
121first = tail;\
122end = NULL; \
123 stt->err = 0; \
124 }
125
126static void reset_list_of_term_vars(Term t USES_REGS)
127{
128 while (IsPairTerm(t)) {
129 Term v = HeadOfTerm(t);
130 RESET_VARIABLE(VarOfTerm(v));
131 t = TailOfTerm(t);
132 }
133}
134
135
136
137
138static Term term_error_handler(Term *bindp, Term t0,Ystack_t *stt) {
139 yhandle_t y0 = Yap_StartHandles();
140 yhandle_t ctx=Yap_InitHandle(t0);
141 if (bindp) {
142 Yap_InitHandle(*bindp);
143 }
144 if (stt->err == RESOURCE_ERROR_AUXILIARY_STACK) {
145 // size_t delta = stt->max-stt->pt0;
146 // size_t nsz = delta > 1024*1024 ? delta+1024+1024 : 2*delta;
147 if (!init_stack(stt)) {
148 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, TermNil, "while visiting terms");
149 }
150 // *pdepth += 4096;
151 } else if (stt->err == RESOURCE_ERROR_TRAIL) {
152
153 if (!Yap_growtrail(0, false)) {
154 Yap_ThrowError(RESOURCE_ERROR_TRAIL, TermNil, "while visiting terms");
155 }
156 } else if (stt->err == RESOURCE_ERROR_STACK) {
157 // printf("In H0=%p Hb=%ld H=%ld G0=%ld GF=%ld ASP=%ld\n",H0, cs->oHB-H0,
158 // cs->oH-H0, ArenaPt(*arenap)-H0,ArenaLimit(*arenap)-H0,(LCL0-cs->oASP)-H0) ;
159 if (!Yap_dogcl(0)) {
160 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
161 }
162 // printf("In H0=%p Hb=%ld H=%ld G0=%ld GF=%ld ASP=%ld\n",H0, cs->oHB-H0,
163 // cs->oH-H0, ArenaPt(*arenap)-H0,ArenaLimit(*arenap)-H0,LCL0-cs->oASP-H0) ;
164 }
165 if (bindp) {
166 *bindp = Yap_GetFromHandle(ctx + 1);
167 }
168 Term tf = Yap_PopHandle(ctx);
169 Yap_CloseHandles(y0);
170 return tf;
171}
172
173
174#define LIST_HOOK_CODE if (IS_VISIT_MARKER(ptd1[0])) { goto found;}
175#define COMPOUND_HOOK_CODE if (IS_VISIT_MARKER(ptd1[0])) { goto found;}
180static Term cyclic_complex_term(Term t USES_REGS) {
181 COPY(pt0_[1]);
182#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
183#include "term_visit.h"
184 /* leave an empty slot to fill in later */
185 // no cycles found
186 return false;
187 found:
188 while (pop_sub_term(stt, NULL, NULL)) {
189 stt->pt0=stt->pt=stt->max=NULL;
190 }
191 return true;
192}
193
194bool Yap_IsCyclicTerm(Term t USES_REGS) {
195 if (IsVarTerm(t)) {
196 return false;
197 } else if (IsPrimitiveTerm(t)) {
198 return false;
199 } else
200 {
201#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
202 return cyclic_complex_term(t PASS_REGS);
203 }
204}
205
206
216static Int cyclic_term(USES_REGS1) /* cyclic_term(+T) */
217{
218
219 Term t=Deref(ARG1);
220 bool rc;
221#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
222 rc = cyclic_complex_term(t PASS_REGS);
223 return rc;
224}
225
226
231#undef LIST_HOOK_CODE
232#undef COMPOUND_HOOK_CODE
233
234#define VAR_HOOK_CODE \
235 while (pop_sub_term(stt, NULL, NULL)) ;\
236 stt->pt0=stt->pt=stt->max=NULL;\
237 return false;
238
239static bool ground_complex_term(Term t USES_REGS) {
240 // pp(pt0_ [1], 0);
241 COPY(pt0_[1]);
242#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
243#include "term_visit.h"
244 return true;
245}
246
247
248bool Yap_IsGroundTerm(Term t) {
249 CACHE_REGS
250 if (IsVarTerm(t)) {
251 return false;
252 } else if (IsPrimitiveTerm(t)) {
253 return true;
254 } else {
255 return ground_complex_term(t PASS_REGS);
256 }
257}
258
267static Int ground(USES_REGS1) /* ground(+T) */
268{
269 Term t;
270 t = Deref(ARG1);
271 if (IsVarTerm(t)) {
272 return false;
273 } else if (IsPrimitiveTerm(t)) {
274 return true;
275 }
276 return ground_complex_term(t PASS_REGS);
277}
278
279#undef VAR_HOOK_CODE
280
281
282#define VAR_HOOK_CODE\
283 if (v == d0) {\
284 while (pop_sub_term(stt, NULL, NULL)) ;\
285 stt->pt0=stt->pt=stt->max=NULL;\
286 return true;\
287}
288
289
290static bool var_in_complex_term(Term t, Term v USES_REGS) {
291 Term v0 = v;
292#define RESET_TERM_VISITOR RESET_TERM_VISITOR_1(v,v0);
293#include "term_visit.h"
294 // all bindings are left trailed.
295 return false;
296 }
297
298static Int var_in_term(USES_REGS1)
299 {
300 Term t = Deref(ARG1), v0;
301 Term v = v0 = Deref(ARG2);
302 return var_in_complex_term(t, v PASS_REGS);
303
304
305
306}
307
308#undef SAVE_EXTRA
309#undef RESTORE_EXTRA
310#undef VAR_HOOK_CODE
311
312#define VAR_HOOK_CODE \
313 if (HR + 1024 > ASP) {\
314 stt->err = RESOURCE_ERROR_STACK;\
315 continue;\
316 }\
317 if (end == NULL) {\
318 first = AbsPair(HR);\
319 } else {\
320 end[0] = AbsPair(HR);\
321 }\
322 HR[0] = (CELL)ptd0;\
323 HR[1] = tail;\
324 end = (HR + 1); \
325 HR += 2;\
326
327
331static Term var_occurrences_in_complex_term(Term t,
332 Term tail USES_REGS) {
333 Term tail0 = tail;
334
335 Term *end = NULL, first = tail;
336 COPY(pt0_[1]);
337#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
338
339#include "term_visit.h"
340 // all bindings are left trailed.
341return first;
342}
343
347static Term vars_in_complex_term(Term t,
348 Term tail USES_REGS) {
349 Term tail0 = tail;
350 Term *end = NULL, first = tail;
351 COPY(pt0_[1]);
352#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
353#include "term_visit.h"
354
355#undef SAVE_EXTRA
356#undef RESTORE_EXTRA
357
358 return Yap_SortList(first PASS_REGS);
359}
360
361#undef SAVE_EXTRA
362#undef RESTORE_EXTRA
363#undef VAR_HOOK_CODE
364
365
366#define VAR_HOOK_CODE mSET(ptd0, TermNone);
367
371static void mark_vars_in_complex_term(Term t USES_REGS) {
372 // this does not trail, because there will be a second visitor
373 COPY(pt0_[1]);
374 CELL *end = NULL;
375#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(t,t,t,end)
376#include "term_visit.h"
377 // all bindings are left trailed.
378return;
379}
380#undef VAR_HOOK_CODE
381
382#define VAR_HOOK_CODE mSET(pt0, TermNone); \
383 if (HR + 1024 > ASP) {\
384 stt->err = RESOURCE_ERROR_STACK;\
385 continue;\
386 }\
387 if (end == NULL) {\
388 first = AbsPair(HR);\
389 } else {\
390 end[0] = AbsPair(HR);\
391 }\
392 HR[0] = (CELL)ptd0;\
393 HR[1] = tail;\
394 end = (HR + 1); \
395 HR += 2;\
396
397
401static Term list_and_mark_vars_in_complex_term(Term t,
402 Term tail USES_REGS) {
403 Term tail0 = tail;
404
405 Term *end = NULL, first = tail;
406 COPY(pt0_[1]);
407#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
408#include "term_visit.h"
409 // all bindings are left trailed.
410return first;
411}
412
413#undef SAVE_EXTRA
414#undef RESTORE_EXTRA
415#undef VAR_HOOK_CODE
416
417
418
419#define ATOMIC_HOOK_CODE if (d0==TermNone) mSET(ptd0,(CELL)ptd0);
420
421
422
426static void unmark_vars_in_complex_term(Term t USES_REGS) {
427 // this does not trail, because there will be a second visitor
428#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0()
429 COPY(pt0_[1]);
430
431#include "term_visit.h"
432 // all bindings are left trailed.
433return;
434}
435
436#undef ATOMIC_HOOK_CODE
437
438
439#define ATOMIC_HOOK_CODE \
440 \
441 if (d0 == TermNone) {\
442 if (HR + 1024 > ASP) {\
443 stt->err = RESOURCE_ERROR_STACK;\
444 continue;\
445 }\
446 if (end == NULL) {\
447 first = AbsPair(HR);\
448 } else {\
449 end[0] = AbsPair(HR);\
450 }\
451 /* next make sure noone will see this, *start = HRs as a variable again */\
452RESET_VARIABLE(ptd0);\
453 HR[0] = (CELL)ptd0;\
454 HR[1] = tail;\
455 end = HR + 1;\
456 HR += 2;\
457}
458
462static Term marked_vars_in_complex_term(Term t,
463 Term tail USES_REGS) {
464 Term tail0=tail;
465 Term *end = NULL, first = tail;
466 COPY(pt0_[1]);
467#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
468#include "term_visit.h"
469 // all bindings are left trailed.
470 return first;
471}
472
481static Int variables_in_term(USES_REGS1) /* variables in term t */
482{
483 Term t, out;
484 t = Deref(ARG1);
485 if (IsVarTerm(t)) {
486 out = MkPairTerm(MkGlobal(t),TermNil);
487 } else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
488 out = TermNil;
489 } else {
490 out = vars_in_complex_term(t, TermNil PASS_REGS);
491 reset_list_of_term_vars(out PASS_REGS);
492 }
493 out = Yap_SortList(out);
494 return Yap_unify(out,ARG2);
495 }
496
504static Int term_variables3(USES_REGS1) /* variables in term t */
505{
506 Term t, out;
507 t = Deref(ARG1);
508 if (IsVarTerm(t)) {
509 out = MkPairTerm(MkGlobal(t),TermNil);
510 } else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
511 out = ARG3;
512 } else {
513 out = vars_in_complex_term(t, Deref(ARG3) PASS_REGS);
514 }
515 reset_list_of_term_vars(out PASS_REGS);
516
517 return Yap_unify(out,ARG2);
518}
519
520
526static Int term_variables_union(USES_REGS1) /* variables in term t */
527{
528
529 Term t[2], out;
530 t[0] = Deref(ARG1);
531 t[1] = Deref(ARG2);
532 out = vars_in_complex_term(AbsPair(t)
533 , TermNil PASS_REGS);
534 reset_list_of_term_vars(out PASS_REGS);
535 return Yap_unify(out,ARG3);
536}
537
542static Int term_variables_difference(USES_REGS1) /* variables in term t */
543{
544 Term t1, t2, out;
545 t2 = Deref(ARG2);
546 // bind them
547 vars_in_complex_term(t2, TermNil PASS_REGS);
548 // list of remainder
549 t1 = Deref(ARG1);
550 out = vars_in_complex_term(t1, TermNil PASS_REGS);
551 reset_list_of_term_vars(out PASS_REGS);
552 return Yap_unify(out,ARG3);
553
554}
555
560static Int term_variables_intersection(USES_REGS1) /* variables in term t */
561{
562 Term t1, t2, out;
563 t2 = Deref(ARG2);
564 // bind them
565 mark_vars_in_complex_term(t2 PASS_REGS);
566 // list of remainder
567 t1 = Deref(ARG1);
568 out = marked_vars_in_complex_term(t1
569 , TermNil PASS_REGS);
570 unmark_vars_in_complex_term(t2 PASS_REGS);
571 return Yap_unify(out,ARG3);
572
573}
574
581Term Yap_TermVariables(Term t, Term t0 USES_REGS) /* variables in term t */
582{
583 Term out;
584 t = Deref(ARG1);
585 if (IsVarTerm(t)) {
586 out = MkPairTerm(MkGlobal(t),TermNil);
587 } else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
588 out = ARG3;
589 } else {
590 out = vars_in_complex_term(t, Deref(ARG3) PASS_REGS);
591 reset_list_of_term_vars(out PASS_REGS);
592 }
593 return out;
594}
595
603static Int term_variables(USES_REGS1) /* variables in term t */
604{
605 if (!Yap_IsListOrPartialListTerm(Deref(ARG2))) {
606 Yap_ThrowError(TYPE_ERROR_LIST, ARG2, "term_variables/2");
607 return false;
608 }
609 Term t, out;
610 t = Deref(ARG1);
611 if (IsVarTerm(t)) {
612 out = MkPairTerm(MkGlobal(t),TermNil);
613 } else if ( IsPrimitiveTerm(t)) {
614 out = TermNil;
615 } else {
616 out = vars_in_complex_term(t, TermNil PASS_REGS);
617 reset_list_of_term_vars(out PASS_REGS);
618 }
619 return Yap_unify(out,ARG2);
620
621}
622
625typedef struct att_rec {
626 CELL *beg, *end, d0;
628
642static Int
643p_new_variables_in_term(USES_REGS1) /* variables within term t */
644{
645 Term t = ARG2;
646 ARG2 = ARG1;
647 ARG1 = t;
648 return term_variables_difference(PASS_REGS1);
649 }
650
651static Int
652free_variables_in_term(USES_REGS1) /* variables within term t */
653{ Term bounds;
654 Term module = CurrentModule;
655
656 Term t = Deref(ARG1);
657 bounds = Deref(ARG2);
658
659
660
661
662 if (IsVarTerm(t)) {
663 t = MkGlobal(t);
664 }
665
666 while (!IsVarTerm(t) && IsApplTerm(t)) {
667 Functor f = FunctorOfTerm(t);
668 if (f == FunctorHat) {
669 bounds = MkPairTerm(ArgOfTerm(1, t), bounds);
670 t = ArgOfTerm(2, t);
671 } else if (f==FunctorModule) { t = Yap_StripModule(t, &module);
672 } else if (f == FunctorCall) {
673 t = ArgOfTerm(1, t);
674 } else if (f == FunctorExecuteInMod) {
675 bounds = ArgOfTerm(2,t);
676t = ArgOfTerm(1, t);
677 } else {
678 break;
679 }
680 }
681
682 Term ts[2];
683ts[0] = module;
684ts[1] = t;
685t = Yap_MkApplTerm(FunctorModule,2,ts);
686 mark_vars_in_complex_term(bounds PASS_REGS);
687 // list of remainder
688 Term d = vars_in_complex_term(t, TermNil PASS_REGS);
689 reset_list_of_term_vars(d PASS_REGS);
690 unmark_vars_in_complex_term(bounds PASS_REGS);
691return Yap_unify( t,ARG2) && Yap_unify(ARG3,d);
692}
693
694#undef SAVE_EXTRA
695#undef RESTORE_EXTRA
696#undef ATOMIC_HOOK_CODE
697
698
699#define VAR_HOOK_CODE \
700 if (!IS_VISIT_MARKER(*ptd0) && GlobalIsAttVar(ptd0)) {\
701 if (HR + 1024 > ASP) { \
702 stt->err = RESOURCE_ERROR_STACK;\
703 continue;\
704 }\
705 if (end == NULL) {\
706 first = AbsPair(HR);\
707 } else {\
708 end[0] = AbsPair(HR);\
709 }\
710 /* next make sure noone will see this, *start = HRs as a variable again */\
711 HR[0] = (CELL)ptd0;HR[1] = tail; \
712 end = HR + 1;\
713 HR += 2;\
714 ptd0[0] = TermNone;\
715ptd0 += 2; \
716dd0 = *ptd0;\
717 mderef_head(d0, dd0, var_in_term_unk); /*DEB_DOOB();*/\
718goto var_in_term_nvar;\
719}
720
724static Term attvars_in_complex_term(Term t,
725 Term tail USES_REGS) {
726 Term *end = NULL, first = tail, tail0 = tail;
727 COPY(pt0_[1]);
728#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
729#include "term_visit.h"
730 // all bindings are left trailed.
731 return first;
732}
733
740static Int term_attvars(USES_REGS1) /* variables in term t */
741{
742 Term t, out;
743 t = Deref(ARG1);
744 if (IsVarTerm(t)) {
745 out = MkPairTerm(MkGlobal(t),TermNil);
746 } else if ( IsPrimitiveTerm(t)) {
747 out = TermNil;
748 } else {
749 out = attvars_in_complex_term(t, TermNil PASS_REGS);
750 unmark_vars_in_complex_term(t);
751 }
752 return Yap_unify(out,ARG2);
753}
754
755
756void mksingleton(Term v, Functor FunctorNumberVars)
757{
758 CELL *pt = HR;
759 HR+=2;
760 YapBind(VarOfTerm(v),AbsAppl(pt));
761 pt[0] = (CELL)FunctorNumberVars;
762 pt[1] = TermUnderscore;
763 // pt[1] = MkIntTerm(vc++);
764}
765
766
767
768
770int Yap_NumberVars(Term t, int numbv, bool handle_singles USES_REGS)
771{
772 int numbv0 = numbv;
773 Functor FunctorNumberVars = Yap_MkFunctor(AtomOfTerm(getAtomicLocalPrologFlag(NUMBERVARS_FUNCTOR_FLAG)), 1);
774 t = Deref(t);
775 if (handle_singles) {
776 Term d = var_occurrences_in_complex_term(t, TermNil PASS_REGS), dn;
777 if (d==0)
778 return 0;
779 if (d==TermNil) return numbv;
780 LOCAL_DoNotWakeUp= true;
781 if ((dn = TailOfTerm(d)) == TermNil) {
782 Term h = HeadOfTerm(d);
783 mksingleton(h,FunctorNumberVars );
784 return numbv;
785 }
786 while (IsPairTerm(d)) {
787 Term h = HeadOfTerm(d);
788 if (IsVarTerm(h)) {
789 if (ASP-HR < 1024)
790 return numbv0-1;
791 mksingleton(h, FunctorNumberVars);
792 } else {
793 CELL *c = RepAppl(h)+1;
794 if (c[0] == TermUnderscore)
795 c[0] = MkIntegerTerm(numbv++);
796 }
797 d = TailOfTerm(d);
798 }
799 LOCAL_DoNotWakeUp = false;
800 } else {
801 Term d = vars_in_complex_term(t, TermNil PASS_REGS);
802 if (d==TermNil) return numbv;
803 LOCAL_DoNotWakeUp = true;
804 while (IsPairTerm(d)) {
805 Term h = HeadOfTerm(d);
806 CELL *pt = HR;
807 if (ASP-HR < 1024)
808 return numbv0-1;
809 HR+=2;
810 YapBind(VarOfTerm(h),AbsAppl(pt));
811 pt[0] = (CELL)FunctorNumberVars;
812 pt[1] = MkIntTerm(numbv++);
813 d = TailOfTerm(d);
814 }
815 }
816 LOCAL_DoNotWakeUp = false;
817 return numbv;
818}
819static Int p_numbervars(USES_REGS1) {
825 size_t out;
826 Term t = Deref(ARG1);
827 Term numbt = Deref(ARG2);
828 if (IsVarTerm(t)) {
829 t = MkGlobal(t);
830 }
831 if (IsVarTerm(numbt)) {
832 Yap_Error(INSTANTIATION_ERROR, numbt, "numbervars/3");
833 return false;
834 }
835 if (!IsIntegerTerm(numbt)) {
836 Yap_Error(TYPE_ERROR_INTEGER, numbt, "numbervars/3");
837 return (false);
838 }
839 Int numbv = IntegerOfTerm(numbt);
840 if (IsPrimitiveTerm(t)) {
841 return Yap_unify(ARG3, numbt);
842 }
843 while (( out = Yap_NumberVars( t, numbv, false PASS_REGS))<numbv) {
844 if (!Yap_dogcl(0)) {
845 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
846 }
847 t = Deref(ARG1);
848 }
849 return Yap_unify(ARG3, MkIntegerTerm(out));
850}
851
860static Int singleton_vs_numbervars(USES_REGS1) {
861 Term t, numbt;
862 size_t out;
863 t = Deref(ARG1);
864 numbt = Deref(ARG2);
865 if (IsVarTerm(t)) {
866 t = MkGlobal(t);
867 }
868 if (IsVarTerm(numbt)) {
869 Yap_Error(INSTANTIATION_ERROR, numbt, "numbervars/3");
870 return false;
871 }
872 if (!IsIntegerTerm(numbt)) {
873 Yap_Error(TYPE_ERROR_INTEGER, numbt, "numbervars/3");
874 return (false);
875 }
876 Int numbv = IntegerOfTerm(numbt);
877 if (IsPrimitiveTerm(t)) {
878 return Yap_unify(ARG3, numbt);
879 }
880 out = Yap_NumberVars( t, numbv, true PASS_REGS);
881 return Yap_unify(ARG3, MkIntegerTerm(out));
882}
883
884#undef VAR_HOOK_CODE
885
886
887#define COMPOUND_HOOK_CODE \
888 if ( f == FunctorNumberVars ) { \
889 if ( ptd1[1] == TermUnderscore ) {\
890 mMaBind(ptd0,(CELL)ptd0); \
891 goto loop; \
892 }\
893 HR[0] = AbsPair(HR+2); \
894 HR[1] = *bp; \
895 *bp = AbsPair(HR);\
896HR[2] = ptd1[1]; /* key */ \
897 HR[3] = (CELL) ptd0; /* variable */ \
898 mMaBind(ptd0,(CELL)ptd0); \
899 bp = HR+1; \
900 HR+= 4;\
901 goto loop; \
902 }
903
904
905static bool unnumbervars_in_complex_term(Term t, CELL *HLow USES_REGS) {
906 CELL *hr0= HR;
907 CELL bindings = TermNil;
908 CELL * bp = &bindings;
909 COPY(pt0_[1]);
910// Numbervars
911 //Functor FunctorNumberVars = Yap_MkFunctor(AtomOfTerm(getAtomicLocalPrologFlag(NUMBERVARS_FUNCTOR_FLAG)), 1);
912Term first, tail0, tail = tail0 = TermNil;
913Term *end;
914#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
915#include "term_visit.h"
916 // all bindings are left trailed.
917 if (bindings == TermNil) return true;
918 t = Yap_MergeSort(AbsPair(hr0) PASS_REGS);
919 if (t==0) {
920 HR = hr0;
921 return 0;
922 }
923 Term v= 0, k=0;
924 while (IsPairTerm(t)) {
925 Term kv = HeadOfTerm(t);
926 if (HeadOfTerm(kv)==k) {
927 mSET(CellPtr(TailOfTerm(kv)), v);
928 } else {
929 k = HeadOfTerm(kv);
930 v = *CellPtr(TailOfTerm(kv));
931 }
932 t = TailOfTerm(t);
933 }
934 HR = hr0;
935 return true;
936}
937
942static Int unnumbervars(USES_REGS1) /* variables in term t */
943{
944 Term t;
945 t = Deref(ARG1);
946 return unnumbervars_in_complex_term(t, NULL PASS_REGS);
947}
948
953Int Yap_UnNumberTerm(Term t, CELL *HLow USES_REGS) /* variables in term t */
954{
955
956 t = Deref(ARG1);
957 Int out = unnumbervars_in_complex_term(t, HLow PASS_REGS);
958 return out;
959}
960
965static Int varnumbers(USES_REGS1) /* variables in term t */
966{
967 Term t0=Deref(ARG1), t, vs0, vs1;
968#define SAVE_EXTRA() yhandle_t yv = Yap_InitHandle(t0)
969#define RESTORE_EXTRA() t0 = Yap_PopHandle(yv)
970
971 vs0 = vars_in_complex_term(t0,TermNil PASS_REGS);
972
973#undef SAVE_EXTRA
974#undef RESTORE_EXTRA
975#define SAVE_EXTRA() yhandle_t yv = Yap_InitHandle(vs0)
976#define RESTORE_EXTRA() {vs0 = Yap_PopHandle(yv);};
977 t = Yap_CopyTerm(MkPairTerm(ARG1,vs0)); vs1 = TailOfTerm(t);
978 t = HeadOfTerm(t);
979 unnumbervars_in_complex_term(t, NULL PASS_REGS);
980 return Yap_unify(vs0,vs1) && Yap_unify(t,ARG2);
981}
982
983void Yap_InitTermCPreds(void) {
984 Yap_InitCPred("cyclic_term", 1, cyclic_term, SafePredFlag);
985
986 Yap_InitCPred("ground", 1, ground, SafePredFlag);
987 Yap_InitCPred("numbervars", 3, p_numbervars, 0);
988 Yap_InitCPred("$singleton_vs_numbervars", 3, singleton_vs_numbervars, 0);
989 CurrentModule = TERMS_MODULE;
990 Yap_InitCPred("variable_in_term", 2, var_in_term, 0);
991 Yap_InitCPred("new_variables_in_term", 3, p_new_variables_in_term, 0);
992 Yap_InitCPred("variables_in_both_terms", 3,term_variables_intersection, 0);
993 CurrentModule = PROLOG_MODULE;
994 Yap_InitCPred("unnumbervars", 1, unnumbervars, 0);
995 // Yap_InitCPred("varnumbers", 2, varnumbers, 0);
996#if 1
997 Yap_InitCPred("term_variables", 2, term_variables, 0);
998 Yap_InitCPred("term_variables", 3, term_variables3, 0);
999 Yap_InitCPred("variables_in_term", 3, variables_in_term, 0);
1000 Yap_InitCPred("$variables_in_term", 3, variables_in_term, 0);
1001
1002 Yap_InitCPred("$free_variables_in_term", 3, free_variables_in_term, 0);
1003 Yap_InitCPred("free_variables_in_term", 3, free_variables_in_term, 0);
1004
1005 Yap_InitCPred("term_attvars", 2, term_attvars, 0);
1006
1007 Yap_InitCPred("variables_in_both_terms", 3, term_variables_intersection, 0);
1008 Yap_InitCPred("variables_in_any_term", 3, term_variables_union, 0);
1009
1010
1011
1012
1013
1014
1015#endif
1016 }
1017
1018
1019
1021
1022
1023
struct att_rec att_rec_t
routine to locate attributed variables
Term Yap_TermVariables(Term t, Term t0 USES_REGS)
Extends list with all the variables in a term.
Definition: terms.c:581
int Yap_NumberVars(Term t, int numbv, bool handle_singles USES_REGS)
numbervariables in term t
Definition: terms.c:770
routine to locate attributed variables
Definition: terms.c:625
Definition: terms.h:25
start of top macro