1 
2 /*
3  * File TermIterators.hpp.
4  *
5  * This file is part of the source code of the software program
6  * Vampire. It is protected by applicable
7  * copyright laws.
8  *
9  * This source code is distributed under the licence found here
10  * https://vprover.github.io/license.html
11  * and in the source directory
12  *
13  * In summary, you are allowed to use Vampire for non-commercial
14  * purposes but not allowed to distribute, modify, copy, create derivatives,
15  * or use in competitions.
16  * For other uses of Vampire please contact developers for a different
17  * licence, which we will make an effort to provide.
18  */
19 /**
20  * @file TermIterators.hpp
21  * Defines several iteratorn over terms.
22  */
23 
24 #ifndef __TermIterators__
25 #define __TermIterators__
26 
27 #include "Forwards.hpp"
28 
29 #include "Lib/Recycler.hpp"
30 #include "Lib/Stack.hpp"
31 #include "Lib/VirtualIterator.hpp"
32 
33 #include "Term.hpp"
34 
35 
36 namespace Kernel {
37 
38 /**
39  * Iterator that yields variables of specified
40  * @b term in DFS left to right order.
41  */
42 class VariableIterator
43 : public IteratorCore<TermList>
44 {
45 public:
46   DECL_ELEMENT_TYPE(TermList);
VariableIterator()47   VariableIterator() : _stack(8), _used(false) {}
48 
VariableIterator(const Term * term)49   VariableIterator(const Term* term) : _stack(8), _used(false)
50   {
51     if(!term->shared() || !term->ground()) {
52       _stack.push(term->args());
53     }
54   }
55 
VariableIterator(TermList t)56   VariableIterator(TermList t) : _stack(8), _used(false)
57   {
58     if(t.isVar()) {
59       _aux[0].makeEmpty();
60       _aux[1]=t;
61       _stack.push(&_aux[1]);
62     }
63     else {
64       Term* term=t.term();
65       if(!term->shared() || !term->ground()) {
66 	_stack.push(term->args());
67       }
68     }
69   }
70 
reset(const Term * term)71   void reset(const Term* term)
72   {
73     _stack.reset();
74     _used = false;
75     if(!term->shared() || !term->ground()) {
76       _stack.push(term->args());
77     }
78   }
79 
reset(TermList t)80   void reset(TermList t)
81   {
82     _stack.reset();
83     _used = false;
84     if(t.isVar()) {
85       _aux[0].makeEmpty();
86       _aux[1]=t;
87       _stack.push(&_aux[1]);
88     }
89     else {
90       Term* term=t.term();
91       if(!term->shared() || !term->ground()) {
92 	_stack.push(term->args());
93       }
94     }
95   }
96 
97 
98   bool hasNext();
99   /** Return the next variable
100    * @warning hasNext() must have been called before */
next()101   TermList next()
102   {
103     ASS(!_used);
104     ASS(_stack.top()->isVar());
105     _used=true;
106     return *_stack.top();
107   }
108 private:
109   Stack<const TermList*> _stack;
110   bool _used;
111   TermList _aux[2];
112 };
113 
114 struct VariableIteratorFn
115 {
116   DECL_RETURN_TYPE(VirtualIterator<TermList>);
operator ()Kernel::VariableIteratorFn117   VirtualIterator<TermList> operator()(Term* t)
118   {
119     return vi( new VariableIterator(t) );
120   }
operator ()Kernel::VariableIteratorFn121   VirtualIterator<TermList> operator()(TermList t)
122   {
123     if(t.isVar()) {
124       return pvi( getSingletonIterator(t) );
125     }
126     else {
127       return (*this)(t.term());
128     }
129   }
130 };
131 
132 struct OrdVarNumberExtractorFn
133 {
134   DECL_RETURN_TYPE(unsigned);
operator ()Kernel::OrdVarNumberExtractorFn135   unsigned operator()(TermList t)
136   {
137     CALL("OrdVarNumberExtractorFn::operator()");
138     ASS(t.isOrdinaryVar());
139 
140     return t.var();
141   }
142 };
143 
144 /**
145  * Iterator that yields proper subterms
146  * of @b term in DFS left to right order.
147  */
148 class SubtermIterator
149   : public IteratorCore<TermList>
150 {
151 public:
SubtermIterator(const Term * term)152   SubtermIterator(const Term* term) : _used(false)
153   {
154     Recycler::get(_stack);
155     _stack->reset();
156 
157     pushNext(term->args());
158   }
~SubtermIterator()159   ~SubtermIterator()
160   {
161     Recycler::release(_stack);
162   }
163 
164   bool hasNext();
165   /** Return next subterm
166    * @warning hasNext() must have been called before */
next()167   TermList next()
168   {
169     ASS(!_used && !_stack->isEmpty());
170     _used=true;
171     return *_stack->top();
172   }
173 
174   /**
175    * Do not iterate subterms of the recently returned term (i.e. go right
176    * rather than down in the term).
177    */
178   void right();
179 protected:
SubtermIterator()180   SubtermIterator() : _used(false)
181   {
182     Recycler::get(_stack);
183     _stack->reset();
184   }
185 
186   inline
pushNext(const TermList * t)187   void pushNext(const TermList* t)
188   {
189     if(!t->isEmpty()) {
190       _stack->push(t);
191     }
192   }
193 
194   Stack<const TermList*>* _stack;
195   bool _used;
196 };
197 
198 /**
199  * Iterator that yields proper subterms of commutative
200  * literal @b lit in DFS left to right order with the
201  * arguments of the literal reversed.
202  */
203 class ReversedCommutativeSubtermIterator
204 : public SubtermIterator
205 {
206 public:
ReversedCommutativeSubtermIterator(const Term * trm)207   ReversedCommutativeSubtermIterator(const Term* trm)
208   {
209     CALL("Term::ReversedCommutativeSubtermIterator::ReversedCommutativeSubtermIterator");
210     ASS(trm->commutative());
211     ASS_EQ(trm->arity(),2);
212 
213     aux[0]=*trm->nthArgument(1);
214     aux[1].makeEmpty();
215     aux[2]=*trm->nthArgument(0);
216     aux[3].makeEmpty();
217 
218     _stack->push(&aux[0]);
219     _stack->push(&aux[2]);
220   }
221 private:
222   TermList aux[4];
223 };
224 
225 /**
226  * Iterator that yields proper subterms
227  * of specified @b term, so that for each function it first yields
228  * its arguments left to right, and then the function itself.
229  */
230 class PolishSubtermIterator
231 : public IteratorCore<TermList>
232 {
233 public:
PolishSubtermIterator(const Term * term)234   PolishSubtermIterator(const Term* term) : _stack(8), _used(false)
235   {
236     pushNext(term->args());
237   }
238 
239   bool hasNext();
240   /** Return next subterm
241    * @warning hasNext() must have been called before */
next()242   TermList next()
243   {
244     ASS(!_used && !_stack.isEmpty());
245     _used=true;
246     return *_stack.top();
247   }
248 private:
249   inline
pushNext(const TermList * t)250   void pushNext(const TermList* t)
251   {
252     while(!t->isEmpty()) {
253       _stack.push(t);
254       if(!t->isTerm()) {
255 	return;
256       }
257       t=t->term()->args();
258     }
259   }
260   Stack<const TermList*> _stack;
261   bool _used;
262 };
263 
264 /**
265  * Iterator that yields non-variable subterms
266  * of specified @b term in DFS left to right order.
267  */
268 class NonVariableIterator
269   : public IteratorCore<TermList>
270 {
271 public:
272   NonVariableIterator(const NonVariableIterator&);
273   /**
274    * Create an iterator. If @c includeSelf is false, then only proper subterms
275    * of @c term will be included.
276    * @since 04/05/2013 Manchester, argument includeSelf added
277    * @author Andrei Voronkov
278    */
NonVariableIterator(Term * term,bool includeSelf=false)279   NonVariableIterator(Term* term,bool includeSelf=false)
280   : _stack(8),
281     _added(0)
282   {
283     CALL("NonVariableIterator::NonVariableIterator");
284     _stack.push(term);
285     if (!includeSelf) {
286       next();
287     }
288   }
289   // NonVariableIterator(TermList ts);
290 
291   /** true if there exists at least one subterm */
hasNext()292   bool hasNext() { return !_stack.isEmpty(); }
293   TermList next();
294   void right();
295 private:
296   /** available non-variable subterms */
297   Stack<Term*> _stack;
298   /** the number of non-variable subterms added at the last iteration, used by right() */
299   int _added;
300 }; // NonVariableIterator
301 
302 /**
303  * Iterator that iterator over disagreement set of two terms
304  * or literals in DFS left to right order.
305  */
306 class DisagreementSetIterator
307 : public IteratorCore<pair<TermList, TermList> >
308 {
309 public:
310   /**
311    * Create an empty disagreement iterator
312    *
313    * In order to be used, it must be reset by the @b reset function
314    */
DisagreementSetIterator()315   DisagreementSetIterator()
316   {
317     _arg1.makeEmpty();
318   }
319 
320   /**
321    * Create an iterator over the disagreement set of two terms
322    */
DisagreementSetIterator(TermList t1,TermList t2,bool disjunctVariables=true)323   DisagreementSetIterator(TermList t1, TermList t2, bool disjunctVariables=true)
324   : _stack(8)
325   {
326     CALL("Term::DisagreementSetIterator::DisagreementSetIterator(TermList...)");
327     reset(t1, t2, disjunctVariables);
328   }
329   /**
330    * Create an iterator over the disagreement set of two terms/literals
331    * with the same top functor
332    */
DisagreementSetIterator(Term * t1,Term * t2,bool disjunctVariables=true)333   DisagreementSetIterator(Term* t1, Term* t2, bool disjunctVariables=true)
334   : _stack(8), _disjunctVariables(disjunctVariables)
335   {
336     CALL("Term::DisagreementSetIterator::DisagreementSetIterator(Term*...)");
337     reset(t1,t2,disjunctVariables);
338   }
339 
reset(TermList t1,TermList t2,bool disjunctVariables=true)340   void reset(TermList t1, TermList t2, bool disjunctVariables=true)
341   {
342     CALL("Term::DisagreementSetIterator::reset(TermList...)");
343     ASS(!t1.isEmpty());
344     ASS(!t2.isEmpty());
345 
346     _stack.reset();
347     _disjunctVariables=disjunctVariables;
348     if(!TermList::sameTop(t1,t2) || (t1.isVar() && disjunctVariables)) {
349       _arg1=t1;
350       _arg2=t2;
351       return;
352     }
353     _arg1.makeEmpty();
354     if(t1.isTerm() && t1.term()->arity()>0) {
355       _stack.push(t1.term()->args());
356       _stack.push(t2.term()->args());
357     }
358   }
359 
reset(Term * t1,Term * t2,bool disjunctVariables=true)360   void reset(Term* t1, Term* t2, bool disjunctVariables=true)
361   {
362     CALL("Term::DisagreementSetIterator::reset(Term*...)");
363     ASS_EQ(t1->functor(), t2->functor());
364 
365     _stack.reset();
366     _disjunctVariables=disjunctVariables;
367 
368     _arg1.makeEmpty();
369     if(t1->arity()>0) {
370       _stack.push(t1->args());
371       _stack.push(t2->args());
372     }
373   }
374 
375   bool hasNext();
376 
377   /** Return next subterm
378    * @warning hasNext() must have been called before */
next()379   pair<TermList, TermList> next()
380   {
381     pair<TermList, TermList> res(_arg1,_arg2);
382     _arg1.makeEmpty();
383     return res;
384   }
385 private:
386   Stack<TermList*> _stack;
387   bool _disjunctVariables;
388   TermList _arg1;
389   TermList _arg2;
390 };
391 
392 
393 
394 /**
395  * Implements an iterator over function symbols of a term.
396  *
397  * Functions are yielded before their subterms.
398  * @since 26/05/2007 Manchester, made from class TermVarIterator
399  */
400 class TermFunIterator
401 : public IteratorCore<unsigned>
402 {
403 public:
404   TermFunIterator (const Term*);
405 
406   bool hasNext();
407   unsigned next();
408 private:
409   /** True if the next symbol is found */
410   bool _hasNext;
411   /** next symbol, previously found */
412   unsigned _next;
413   /** Stack of term lists (not terms!) */
414   Stack<const TermList*> _stack;
415 }; // class TermFunIterator
416 
417 
418 /**
419  * Implements an iterator over variables of a term term list, or atom.
420  * @since 06/01/2004 Manchester
421  * @since 26/05/2007 Manchester, reimplemented for different data structures
422  */
423 class TermVarIterator
424 : public IteratorCore<unsigned>
425 {
426 public:
427   TermVarIterator (const Term*);
428   TermVarIterator (const TermList*);
429 
430   bool hasNext ();
431   unsigned next ();
432 private:
433   /** True if the next variable is found */
434   // bool _hasNext; // MS: unused
435   /** next variable, previously found */
436   unsigned _next;
437   /** Stack of term lists (not terms!) */
438   Stack<const TermList*> _stack;
439 }; // class TermVarIterator
440 
441 
442 
443 }
444 
445 #endif // __TermIterators__
446