47#define DEB_DOOBOUT(d0) \
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;\
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,
73static inline bool pop_sub_term__(
Ystack_t *sp, CELL **b, CELL **e) {
78 if (pt->oldp != NULL && *pt->oldp)
79 pt->oldp[0] = pt->oldv;
87#define RESET_TERM_VISITOR_0() \
88 if (stt->err){ Term* pt0,*pt0_end;\
89 while ((pop_sub_term(stt, &pt0, &pt0_end))){} ; \
93 t = term_error_handler(stt->bindp,t,stt); \
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))){} ; \
103yhandle_t yv = Yap_InitHandle(v0); \
104 t = term_error_handler(stt->bindp,t,stt); \
106v = v0=Yap_PopHandle(yv); \
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))){}; \
117 yhandle_t yv = Yap_InitHandle(tail0);\
118 t = term_error_handler(stt->bindp,t,stt); \
119 tail0 = Yap_PopHandle(yv);\
126static void reset_list_of_term_vars(Term t USES_REGS)
128 while (IsPairTerm(t)) {
129 Term v = HeadOfTerm(t);
130 RESET_VARIABLE(VarOfTerm(v));
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);
142 Yap_InitHandle(*bindp);
144 if (stt->err == RESOURCE_ERROR_AUXILIARY_STACK) {
147 if (!init_stack(stt)) {
148 Yap_ThrowError(RESOURCE_ERROR_AUXILIARY_STACK, TermNil,
"while visiting terms");
151 }
else if (stt->err == RESOURCE_ERROR_TRAIL) {
153 if (!Yap_growtrail(0,
false)) {
154 Yap_ThrowError(RESOURCE_ERROR_TRAIL, TermNil,
"while visiting terms");
156 }
else if (stt->err == RESOURCE_ERROR_STACK) {
160 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
166 *bindp = Yap_GetFromHandle(ctx + 1);
168 Term tf = Yap_PopHandle(ctx);
169 Yap_CloseHandles(y0);
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) {
182#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
188 while (pop_sub_term(stt, NULL, NULL)) {
189 stt->pt0=stt->pt=stt->max=NULL;
194bool Yap_IsCyclicTerm(Term t USES_REGS) {
197 }
else if (IsPrimitiveTerm(t)) {
201#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
202 return cyclic_complex_term(t PASS_REGS);
216static Int cyclic_term(USES_REGS1)
221#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
222 rc = cyclic_complex_term(t PASS_REGS);
232#undef COMPOUND_HOOK_CODE
234#define VAR_HOOK_CODE \
235 while (pop_sub_term(stt, NULL, NULL)) ;\
236 stt->pt0=stt->pt=stt->max=NULL;\
239static bool ground_complex_term(Term t USES_REGS) {
242#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0();
248bool Yap_IsGroundTerm(Term t) {
252 }
else if (IsPrimitiveTerm(t)) {
255 return ground_complex_term(t PASS_REGS);
267static Int ground(USES_REGS1)
273 }
else if (IsPrimitiveTerm(t)) {
276 return ground_complex_term(t PASS_REGS);
282#define VAR_HOOK_CODE\
284 while (pop_sub_term(stt, NULL, NULL)) ;\
285 stt->pt0=stt->pt=stt->max=NULL;\
290static bool var_in_complex_term(Term t, Term v USES_REGS) {
292#define RESET_TERM_VISITOR RESET_TERM_VISITOR_1(v,v0);
298static Int var_in_term(USES_REGS1)
300 Term t = Deref(ARG1), v0;
301 Term v = v0 = Deref(ARG2);
302 return var_in_complex_term(t, v PASS_REGS);
312#define VAR_HOOK_CODE \
313 if (HR + 1024 > ASP) {\
314 stt->err = RESOURCE_ERROR_STACK;\
318 first = AbsPair(HR);\
320 end[0] = AbsPair(HR);\
331static Term var_occurrences_in_complex_term(Term t,
332 Term tail USES_REGS) {
335 Term *end = NULL, first = tail;
337#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
347static Term vars_in_complex_term(Term t,
348 Term tail USES_REGS) {
350 Term *end = NULL, first = tail;
352#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
358 return Yap_SortList(first PASS_REGS);
366#define VAR_HOOK_CODE mSET(ptd0, TermNone);
371static void mark_vars_in_complex_term(Term t USES_REGS) {
375#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(t,t,t,end)
382#define VAR_HOOK_CODE mSET(pt0, TermNone); \
383 if (HR + 1024 > ASP) {\
384 stt->err = RESOURCE_ERROR_STACK;\
388 first = AbsPair(HR);\
390 end[0] = AbsPair(HR);\
401static Term list_and_mark_vars_in_complex_term(Term t,
402 Term tail USES_REGS) {
405 Term *end = NULL, first = tail;
407#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
419#define ATOMIC_HOOK_CODE if (d0==TermNone) mSET(ptd0,(CELL)ptd0);
426static void unmark_vars_in_complex_term(Term t USES_REGS) {
428#define RESET_TERM_VISITOR RESET_TERM_VISITOR_0()
436#undef ATOMIC_HOOK_CODE
439#define ATOMIC_HOOK_CODE \
441 if (d0 == TermNone) {\
442 if (HR + 1024 > ASP) {\
443 stt->err = RESOURCE_ERROR_STACK;\
447 first = AbsPair(HR);\
449 end[0] = AbsPair(HR);\
452RESET_VARIABLE(ptd0);\
462static Term marked_vars_in_complex_term(Term t,
463 Term tail USES_REGS) {
465 Term *end = NULL, first = tail;
467#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
481static Int variables_in_term(USES_REGS1)
486 out = MkPairTerm(MkGlobal(t),TermNil);
487 }
else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
490 out = vars_in_complex_term(t, TermNil PASS_REGS);
491 reset_list_of_term_vars(out PASS_REGS);
493 out = Yap_SortList(out);
494 return Yap_unify(out,ARG2);
504static Int term_variables3(USES_REGS1)
509 out = MkPairTerm(MkGlobal(t),TermNil);
510 }
else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
513 out = vars_in_complex_term(t, Deref(ARG3) PASS_REGS);
515 reset_list_of_term_vars(out PASS_REGS);
517 return Yap_unify(out,ARG2);
526static Int term_variables_union(USES_REGS1)
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);
542static Int term_variables_difference(USES_REGS1)
547 vars_in_complex_term(t2, TermNil PASS_REGS);
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);
560static Int term_variables_intersection(USES_REGS1)
565 mark_vars_in_complex_term(t2 PASS_REGS);
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);
586 out = MkPairTerm(MkGlobal(t),TermNil);
587 }
else if (!IsVarTerm(t) && IsPrimitiveTerm(t)) {
590 out = vars_in_complex_term(t, Deref(ARG3) PASS_REGS);
591 reset_list_of_term_vars(out PASS_REGS);
603static Int term_variables(USES_REGS1)
605 if (!Yap_IsListOrPartialListTerm(Deref(ARG2))) {
606 Yap_ThrowError(TYPE_ERROR_LIST, ARG2,
"term_variables/2");
612 out = MkPairTerm(MkGlobal(t),TermNil);
613 }
else if ( IsPrimitiveTerm(t)) {
616 out = vars_in_complex_term(t, TermNil PASS_REGS);
617 reset_list_of_term_vars(out PASS_REGS);
619 return Yap_unify(out,ARG2);
643p_new_variables_in_term(USES_REGS1)
648 return term_variables_difference(PASS_REGS1);
652free_variables_in_term(USES_REGS1)
654 Term module = CurrentModule;
656 Term t = Deref(ARG1);
657 bounds = Deref(ARG2);
666 while (!IsVarTerm(t) && IsApplTerm(t)) {
668 if (f == FunctorHat) {
669 bounds = MkPairTerm(ArgOfTerm(1, t), bounds);
671 }
else if (f==FunctorModule) { t = Yap_StripModule(t, &module);
672 }
else if (f == FunctorCall) {
674 }
else if (f == FunctorExecuteInMod) {
675 bounds = ArgOfTerm(2,t);
685t = Yap_MkApplTerm(FunctorModule,2,ts);
686 mark_vars_in_complex_term(bounds PASS_REGS);
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);
696#undef ATOMIC_HOOK_CODE
699#define VAR_HOOK_CODE \
700 if (!IS_VISIT_MARKER(*ptd0) && GlobalIsAttVar(ptd0)) {\
701 if (HR + 1024 > ASP) { \
702 stt->err = RESOURCE_ERROR_STACK;\
706 first = AbsPair(HR);\
708 end[0] = AbsPair(HR);\
711 HR[0] = (CELL)ptd0;HR[1] = tail; \
717 mderef_head(d0, dd0, var_in_term_unk); \
718goto var_in_term_nvar;\
724static Term attvars_in_complex_term(Term t,
725 Term tail USES_REGS) {
726 Term *end = NULL, first = tail, tail0 = tail;
728#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
740static Int term_attvars(USES_REGS1)
745 out = MkPairTerm(MkGlobal(t),TermNil);
746 }
else if ( IsPrimitiveTerm(t)) {
749 out = attvars_in_complex_term(t, TermNil PASS_REGS);
750 unmark_vars_in_complex_term(t);
752 return Yap_unify(out,ARG2);
756void mksingleton(Term v,
Functor FunctorNumberVars)
760 YapBind(VarOfTerm(v),AbsAppl(pt));
761 pt[0] = (CELL)FunctorNumberVars;
762 pt[1] = TermUnderscore;
773 Functor FunctorNumberVars = Yap_MkFunctor(AtomOfTerm(getAtomicLocalPrologFlag(NUMBERVARS_FUNCTOR_FLAG)), 1);
775 if (handle_singles) {
776 Term d = var_occurrences_in_complex_term(t, TermNil PASS_REGS), dn;
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 );
786 while (IsPairTerm(d)) {
787 Term h = HeadOfTerm(d);
791 mksingleton(h, FunctorNumberVars);
793 CELL *c = RepAppl(h)+1;
794 if (c[0] == TermUnderscore)
795 c[0] = MkIntegerTerm(numbv++);
799 LOCAL_DoNotWakeUp =
false;
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);
810 YapBind(VarOfTerm(h),AbsAppl(pt));
811 pt[0] = (CELL)FunctorNumberVars;
812 pt[1] = MkIntTerm(numbv++);
816 LOCAL_DoNotWakeUp =
false;
819static Int p_numbervars(USES_REGS1) {
826 Term t = Deref(ARG1);
827 Term numbt = Deref(ARG2);
831 if (IsVarTerm(numbt)) {
832 Yap_Error(INSTANTIATION_ERROR, numbt,
"numbervars/3");
835 if (!IsIntegerTerm(numbt)) {
836 Yap_Error(TYPE_ERROR_INTEGER, numbt,
"numbervars/3");
839 Int numbv = IntegerOfTerm(numbt);
840 if (IsPrimitiveTerm(t)) {
841 return Yap_unify(ARG3, numbt);
843 while (( out =
Yap_NumberVars( t, numbv,
false PASS_REGS))<numbv) {
845 Yap_ThrowError(RESOURCE_ERROR_STACK, TermNil, LOCAL_ErrorMessage);
849 return Yap_unify(ARG3, MkIntegerTerm(out));
860static Int singleton_vs_numbervars(USES_REGS1) {
868 if (IsVarTerm(numbt)) {
869 Yap_Error(INSTANTIATION_ERROR, numbt,
"numbervars/3");
872 if (!IsIntegerTerm(numbt)) {
873 Yap_Error(TYPE_ERROR_INTEGER, numbt,
"numbervars/3");
876 Int numbv = IntegerOfTerm(numbt);
877 if (IsPrimitiveTerm(t)) {
878 return Yap_unify(ARG3, numbt);
881 return Yap_unify(ARG3, MkIntegerTerm(out));
887#define COMPOUND_HOOK_CODE \
888 if ( f == FunctorNumberVars ) { \
889 if ( ptd1[1] == TermUnderscore ) {\
890 mMaBind(ptd0,(CELL)ptd0); \
893 HR[0] = AbsPair(HR+2); \
897 HR[3] = (CELL) ptd0; \
898 mMaBind(ptd0,(CELL)ptd0); \
905static bool unnumbervars_in_complex_term(Term t, CELL *HLow USES_REGS) {
907 CELL bindings = TermNil;
908 CELL * bp = &bindings;
912Term first, tail0, tail = tail0 = TermNil;
914#define RESET_TERM_VISITOR RESET_TERM_VISITOR_3(first,tail,tail0,end)
917 if (bindings == TermNil)
return true;
918 t = Yap_MergeSort(AbsPair(hr0) PASS_REGS);
924 while (IsPairTerm(t)) {
925 Term kv = HeadOfTerm(t);
926 if (HeadOfTerm(kv)==k) {
927 mSET(CellPtr(TailOfTerm(kv)), v);
930 v = *CellPtr(TailOfTerm(kv));
942static Int unnumbervars(USES_REGS1)
946 return unnumbervars_in_complex_term(t, NULL PASS_REGS);
953Int Yap_UnNumberTerm(Term t, CELL *HLow USES_REGS)
957 Int out = unnumbervars_in_complex_term(t, HLow PASS_REGS);
965static Int varnumbers(USES_REGS1)
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)
971 vs0 = vars_in_complex_term(t0,TermNil PASS_REGS);
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);
979 unnumbervars_in_complex_term(t, NULL PASS_REGS);
980 return Yap_unify(vs0,vs1) && Yap_unify(t,ARG2);
983void Yap_InitTermCPreds(
void) {
984 Yap_InitCPred(
"cyclic_term", 1, cyclic_term, SafePredFlag);
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);
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);
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);
1005 Yap_InitCPred(
"term_attvars", 2, term_attvars, 0);
1007 Yap_InitCPred(
"variables_in_both_terms", 3, term_variables_intersection, 0);
1008 Yap_InitCPred(
"variables_in_any_term", 3, term_variables_union, 0);
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.
int Yap_NumberVars(Term t, int numbv, bool handle_singles USES_REGS)
numbervariables in term t
routine to locate attributed variables