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