1 2 /* 3 * File Term.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 Term.hpp 21 * Defines class Term (also serving as term arguments) 22 * 23 * @since 18/04/2006 Bellevue 24 * @since 06/05/2007 Manchester, changed into a single class instead of three 25 */ 26 27 #ifndef __Term__ 28 #define __Term__ 29 30 #include <cstdlib> 31 #include <iosfwd> 32 #include <utility> 33 34 #include "Forwards.hpp" 35 #include "Debug/Assertion.hpp" 36 #include "Debug/Tracer.hpp" 37 38 #include "Lib/Allocator.hpp" 39 #include "Lib/Portability.hpp" 40 #include "Lib/XML.hpp" 41 #include "Lib/Comparison.hpp" 42 #include "Lib/Stack.hpp" 43 #include "Lib/Metaiterators.hpp" 44 #include "Lib/VString.hpp" 45 46 // #include "MatchTag.hpp" // MS: disconnecting MatchTag, January 2017 47 #define USE_MATCH_TAG 0 48 49 #include "Sorts.hpp" 50 51 #define TERM_DIST_VAR_UNKNOWN 0x7FFFFF 52 53 namespace Kernel { 54 55 using namespace std; 56 using namespace Lib; 57 58 /** Tag denoting the kind of this term 59 * @since 19/02/2008 Manchester, moved outside of the Term class 60 */ 61 enum TermTag { 62 /** reference to another term */ 63 REF = 0u, 64 /** ordinary variable */ 65 ORD_VAR = 1u, 66 /** (function) symbol */ 67 FUN = 2u, 68 /** special variable */ 69 SPEC_VAR = 3u, 70 }; 71 72 /** 73 * Class containing either a pointer to a compound term or 74 * a variable number or a functor. 75 */ 76 class TermList { 77 public: 78 /** dummy constructor, does nothing */ TermList()79 TermList() {} 80 /** creates a term list and initialises its content with data */ TermList(size_t data)81 explicit TermList(size_t data) : _content(data) {} 82 /** creates a term list containing a pointer to a term */ TermList(Term * t)83 explicit TermList(Term* t) : _term(t) {} 84 /** creates a term list containing a variable. If @b special is true, then the variable 85 * will be "special". Special variables are also variables, with a difference that a 86 * special variables and ordinary variables have an empty intersection */ TermList(unsigned var,bool special)87 TermList(unsigned var, bool special) 88 { 89 if (special) { 90 makeSpecialVar(var); 91 } 92 else { 93 makeVar(var); 94 } 95 } 96 97 /** the tag */ tag() const98 inline TermTag tag() const { return (TermTag)(_content & 0x0003); } 99 /** the term list is empty */ isEmpty() const100 inline bool isEmpty() const 101 { return tag() == FUN; } 102 /** the term list is non-empty */ isNonEmpty() const103 inline bool isNonEmpty() const 104 { return tag() != FUN; } 105 /** next term in this list */ next()106 inline TermList* next() 107 { return this-1; } 108 /** next term in this list */ next() const109 inline const TermList* next() const 110 { return this-1; } 111 /** the term contains a variable as its head */ isVar() const112 inline bool isVar() const { return (_content & 0x0001) == 1; } 113 /** the term contains an ordinary variable as its head */ isOrdinaryVar() const114 inline bool isOrdinaryVar() const { return tag() == ORD_VAR; } 115 /** the term contains a special variable as its head */ isSpecialVar() const116 inline bool isSpecialVar() const { return tag() == SPEC_VAR; } 117 /** return the variable number */ var() const118 inline unsigned var() const 119 { ASS(isVar()); return _content / 4; } 120 /** the term contains reference to Term class */ isTerm() const121 inline bool isTerm() const 122 { return tag() == REF; } term() const123 inline const Term* term() const 124 { ASS(isTerm()); return _term; } term()125 inline Term* term() 126 { ASS(isTerm()); return _term; } 127 /** True of the terms have the same content. Useful for comparing 128 * arguments of shared terms. */ sameContent(const TermList * t) const129 inline bool sameContent(const TermList* t) const 130 { return _content == t->_content ; } 131 /** return the content, useful for e.g., term argument comparison */ content() const132 inline size_t content() const { return _content; } 133 vstring toString() const; 134 /** make the term into an ordinary variable with a given number */ makeVar(unsigned vnumber)135 inline void makeVar(unsigned vnumber) 136 { _content = vnumber * 4 + ORD_VAR; } 137 /** make the term into a special variable with a given number */ makeSpecialVar(unsigned vnumber)138 inline void makeSpecialVar(unsigned vnumber) 139 { _content = vnumber * 4 + SPEC_VAR; } 140 /** make the term empty (so that isEmpty() returns true) */ makeEmpty()141 inline void makeEmpty() 142 { _content = FUN; } 143 /** make the term into a reference */ setTerm(Term * t)144 inline void setTerm(Term* t) 145 { _term = t; } 146 static bool sameTop(TermList ss, TermList tt); 147 static bool sameTopFunctor(TermList ss, TermList tt); 148 static bool equals(TermList t1, TermList t2); 149 static bool allShared(TermList* args); var(unsigned var,bool special=false)150 static TermList var(unsigned var, bool special = false) { return TermList(var, special); } 151 /** if not var, the inner term must be shared */ 152 unsigned weight() const; 153 bool containsSubterm(TermList v); 154 bool containsAllVariablesOf(TermList t); 155 bool containsAllVariableOccurrencesOf(TermList t); 156 157 bool isSafe() const; 158 159 IntList* freeVariables() const; 160 161 #if VDEBUG 162 void assertValid() const; 163 #endif 164 operator ==(const TermList & t) const165 inline bool operator==(const TermList& t) const 166 { return _content==t._content; } operator !=(const TermList & t) const167 inline bool operator!=(const TermList& t) const 168 { return _content!=t._content; } operator <(const TermList & t) const169 inline bool operator<(const TermList& t) const 170 { return _content<t._content; } operator >(const TermList & t) const171 inline bool operator>(const TermList& t) const 172 { return _content>t._content; } 173 174 private: 175 vstring asArgsToString() const; 176 177 union { 178 /** reference to another term */ 179 Term* _term; 180 /** raw content, can be anything */ 181 size_t _content; 182 /** Used by Term, storing some information about the term using bits */ 183 struct { 184 /** tag, always FUN */ 185 unsigned tag : 2; 186 /** polarity, used only for literals */ 187 unsigned polarity : 1; 188 /** true if commutative/symmetric */ 189 unsigned commutative : 1; 190 /** true if shared */ 191 unsigned shared : 1; 192 /** true if literal */ 193 unsigned literal : 1; 194 /** Ordering comparison result for commutative term arguments, one of 195 * 0 (unknown) 1 (less), 2 (equal), 3 (greater), 4 (incomparable) 196 * @see Term::ArgumentOrder */ 197 unsigned order : 3; 198 /** Number of distincs variables in the term, equal 199 * to TERM_DIST_VAR_UNKNOWN if the number has not been 200 * computed yet. */ 201 mutable unsigned distinctVars : 23; 202 /** reserved for whatever */ 203 #if ARCH_X64 204 # if USE_MATCH_TAG 205 MatchTag matchTag; //32 bits 206 # else 207 unsigned reserved : 32; 208 # endif 209 #else 210 // unsigned reserved : 0; 211 #endif 212 } _info; 213 }; 214 friend class Indexing::TermSharing; 215 friend class Term; 216 friend class Literal; 217 }; // class TermList 218 219 ASS_STATIC(sizeof(TermList)==sizeof(size_t)); 220 221 /** 222 * Class to represent terms and lists of terms. 223 * @since 19/02/2008 Manchester, changed to use class TermList 224 */ 225 class Term 226 { 227 public: 228 //special functor values 229 static const unsigned SF_ITE = 0xFFFFFFFF; 230 static const unsigned SF_LET = 0xFFFFFFFE; 231 static const unsigned SF_FORMULA = 0xFFFFFFFD; 232 static const unsigned SF_TUPLE = 0xFFFFFFFC; 233 static const unsigned SF_LET_TUPLE = 0xFFFFFFFB; 234 static const unsigned SPECIAL_FUNCTOR_LOWER_BOUND = 0xFFFFFFFB; 235 236 class SpecialTermData 237 { 238 friend class Term; 239 private: 240 union { 241 struct { 242 Formula * condition; 243 unsigned sort; 244 } _iteData; 245 struct { 246 unsigned functor; 247 IntList* variables; 248 //The size_t stands for TermList expression which cannot be here 249 //since C++ doesnot allow objects with constructor inside a union 250 size_t binding; 251 unsigned sort; 252 } _letData; 253 struct { 254 Formula * formula; 255 } _formulaData; 256 struct { 257 Term* term; 258 } _tupleData; 259 struct { 260 unsigned functor; 261 IntList* symbols; 262 size_t binding; 263 unsigned sort; 264 } _letTupleData; 265 }; 266 /** Return pointer to the term to which this object is attached */ getTerm() const267 const Term* getTerm() const { return reinterpret_cast<const Term*>(this+1); } 268 public: getType() const269 unsigned getType() const { 270 unsigned res = getTerm()->functor(); 271 ASS_GE(res,SPECIAL_FUNCTOR_LOWER_BOUND); 272 return res; 273 } getCondition() const274 Formula* getCondition() const { ASS_EQ(getType(), SF_ITE); return _iteData.condition; } getFunctor() const275 unsigned getFunctor() const { 276 ASS_REP(getType() == SF_LET || getType() == SF_LET_TUPLE, getType()); 277 return getType() == SF_LET ? _letData.functor : _letTupleData.functor; 278 } getVariables() const279 IntList* getVariables() const { ASS_EQ(getType(), SF_LET); return _letData.variables; } getTupleSymbols() const280 IntList* getTupleSymbols() const { return _letTupleData.symbols; } getBinding() const281 TermList getBinding() const { 282 ASS_REP(getType() == SF_LET || getType() == SF_LET_TUPLE, getType()); 283 return TermList(getType() == SF_LET ? _letData.binding : _letTupleData.binding); 284 } getSort() const285 unsigned getSort() const { 286 switch (getType()) { 287 case SF_ITE: 288 return _iteData.sort; 289 case SF_LET: 290 return _letData.sort; 291 case SF_LET_TUPLE: 292 return _letTupleData.sort; 293 default: 294 ASSERTION_VIOLATION_REP(getType()); 295 } 296 } getFormula() const297 Formula* getFormula() const { ASS_EQ(getType(), SF_FORMULA); return _formulaData.formula; } getTupleTerm() const298 Term* getTupleTerm() const { return _tupleData.term; } 299 }; 300 301 302 Term() throw(); 303 explicit Term(const Term& t) throw(); 304 static Term* create(unsigned function, unsigned arity, const TermList* args); 305 static Term* create(unsigned fn, std::initializer_list<TermList> args); 306 static Term* create(Term* t,TermList* args); 307 static Term* createNonShared(Term* t,TermList* args); 308 static Term* createNonShared(Term* t); 309 static Term* cloneNonShared(Term* t); 310 311 static Term* createConstant(const vstring& name); 312 /** Create a new constant and insert in into the sharing structure */ createConstant(unsigned symbolNumber)313 static Term* createConstant(unsigned symbolNumber) { return create(symbolNumber,0,0); } 314 static Term* createITE(Formula * condition, TermList thenBranch, TermList elseBranch, unsigned branchSort); 315 static Term* createLet(unsigned functor, IntList* variables, TermList binding, TermList body, unsigned bodySort); 316 static Term* createTupleLet(unsigned functor, IntList* symbols, TermList binding, TermList body, unsigned bodySort); 317 static Term* createFormula(Formula* formula); 318 static Term* createTuple(unsigned arity, unsigned* sorts, TermList* elements); 319 static Term* createTuple(Term* tupleTerm); 320 static Term* create1(unsigned fn, TermList arg); 321 static Term* create2(unsigned fn, TermList arg1, TermList arg2); 322 323 //** fool constants 324 static Term* foolTrue(); 325 static Term* foolFalse(); 326 327 IntList* freeVariables() const; 328 329 /** Return number of bytes before the start of the term that belong to it */ getPreDataSize()330 size_t getPreDataSize() { return isSpecial() ? sizeof(SpecialTermData) : 0; } 331 332 /** Function or predicate symbol of a term */ functor() const333 const unsigned functor() const { return _functor; } 334 335 static XMLElement variableToXML(unsigned var); 336 vstring toString() const; 337 static vstring variableToString(unsigned var); 338 static vstring variableToString(TermList var); 339 /** return the arguments */ args() const340 const TermList* args() const 341 { return _args + _arity; } 342 /** return the nth argument (counting from 0) */ nthArgument(int n) const343 const TermList* nthArgument(int n) const 344 { 345 ASS(n >= 0); 346 ASS((unsigned)n < _arity); 347 348 return _args + (_arity - n); 349 } 350 /** return the nth argument (counting from 0) */ nthArgument(int n)351 TermList* nthArgument(int n) 352 { 353 ASS(n >= 0); 354 ASS((unsigned)n < _arity); 355 356 return _args + (_arity - n); 357 } 358 /** Indexing operator for accessing arguments */ operator [](int i) const359 const TermList operator[](int i) const { 360 return *nthArgument(i); 361 } operator [](int i)362 TermList operator[](int i) { 363 return *nthArgument(i); 364 } 365 /** return the arguments */ args()366 TermList* args() 367 { return _args + _arity; } 368 unsigned hash() const; 369 /** return the arity */ arity() const370 unsigned arity() const 371 { return _arity; } 372 static void* operator new(size_t,unsigned arity,size_t preData=0); 373 /** make the term into a symbol term */ makeSymbol(unsigned number,unsigned arity)374 void makeSymbol(unsigned number,unsigned arity) 375 { 376 _functor = number; 377 _arity = arity; 378 } 379 void destroy(); 380 void destroyNonShared(); 381 Term* apply(Substitution& subst); 382 383 /** True if the term is ground. Only applicable to shared terms */ ground() const384 bool ground() const 385 { 386 ASS(_args[0]._info.shared); 387 return ! vars(); 388 } // ground 389 390 /** True if the term is shared */ shared() const391 bool shared() const 392 { return _args[0]._info.shared; } // shared 393 394 /** 395 * True if the term's function/predicate symbol is commutative/symmetric. 396 * @pre the term must be complex 397 */ commutative() const398 bool commutative() const 399 { 400 return _args[0]._info.commutative; 401 } // commutative 402 403 /** Return the weight. Applicable only to shared terms */ weight() const404 unsigned weight() const 405 { 406 ASS(shared()); 407 return _weight; 408 } 409 410 /** Mark term as shared */ markShared()411 void markShared() 412 { 413 ASS(! shared()); 414 _args[0]._info.shared = 1u; 415 } // markShared 416 417 /** Set term weight */ setWeight(unsigned w)418 void setWeight(unsigned w) 419 { 420 _weight = w; 421 } // setWeight 422 423 /** Set term id */ setId(unsigned id)424 void setId(unsigned id) 425 { 426 _id = id; 427 } // setWeight 428 429 /** Set (shared) term's id */ getId() const430 unsigned getId() const 431 { 432 ASS(shared()); 433 return _id; 434 } 435 436 /** Set the number of variables */ setVars(unsigned v)437 void setVars(unsigned v) 438 { 439 CALL("Term::setVars"); 440 441 if(_isTwoVarEquality) { 442 ASS_EQ(v,2); 443 return; 444 } 445 _vars = v; 446 } // setVars 447 448 /** Return the number of variables */ vars() const449 unsigned vars() const 450 { 451 ASS(shared()); 452 if(_isTwoVarEquality) { 453 return 2; 454 } 455 return _vars; 456 } // vars() 457 458 /** 459 * Return true iff the object is an equality between two variables. 460 * 461 * This value is set during insertion into the term sharing structure or 462 * for terms with special subterms during construction. 463 * (I.e. can be used basically anywhere). 464 */ isTwoVarEquality() const465 bool isTwoVarEquality() const 466 { 467 return _isTwoVarEquality; 468 } 469 470 const vstring& functionName() const; 471 472 /** True if the term is, in fact, a literal */ isLiteral() const473 bool isLiteral() const { return _args[0]._info.literal; } 474 475 /** Return an index of the argument to which @b arg points */ getArgumentIndex(TermList * arg)476 unsigned getArgumentIndex(TermList* arg) 477 { 478 CALL("Term::getArgumentIndex"); 479 480 unsigned res=arity()-(arg-_args); 481 ASS_L(res,arity()); 482 return res; 483 } 484 485 #if VDEBUG 486 vstring headerToString() const; 487 void assertValid() const; 488 #endif 489 490 491 static TermIterator getVariableIterator(TermList tl); 492 493 // static Comparison lexicographicCompare(TermList t1, TermList t2); 494 // static Comparison lexicographicCompare(Term* t1, Term* t2); 495 496 /** If number of distinct variables is computed, assign it to res and 497 * return true, otherwise return false. */ askDistinctVars(unsigned & res) const498 bool askDistinctVars(unsigned& res) const 499 { 500 if(_args[0]._info.distinctVars==TERM_DIST_VAR_UNKNOWN) { 501 return false; 502 } 503 res=_args[0]._info.distinctVars; 504 return true; 505 } getDistinctVars() const506 unsigned getDistinctVars() const 507 { 508 if(_args[0]._info.distinctVars==TERM_DIST_VAR_UNKNOWN) { 509 unsigned res=computeDistinctVars(); 510 if(res<TERM_DIST_VAR_UNKNOWN) { 511 _args[0]._info.distinctVars=res; 512 } 513 return res; 514 } else { 515 ASS_L(_args[0]._info.distinctVars,0x100000); 516 return _args[0]._info.distinctVars; 517 } 518 } 519 couldBeInstanceOf(Term * t)520 bool couldBeInstanceOf(Term* t) 521 { 522 ASS(shared()); 523 ASS(t->shared()); 524 if(t->functor()!=functor()) { 525 return false; 526 } 527 ASS(!commutative()); 528 return couldArgsBeInstanceOf(t); 529 } couldArgsBeInstanceOf(Term * t)530 inline bool couldArgsBeInstanceOf(Term* t) 531 { 532 #if USE_MATCH_TAG 533 ensureMatchTag(); 534 t->ensureMatchTag(); 535 return matchTag().couldBeInstanceOf(t->matchTag()); 536 #else 537 return true; 538 #endif 539 } 540 541 bool containsSubterm(TermList v); 542 bool containsAllVariablesOf(Term* t); 543 size_t countSubtermOccurrences(TermList subterm); 544 /** Return true if term has no non-constant functions as subterms */ 545 bool isShallow() const; 546 547 /** set the colour of the term */ setColor(Color color)548 void setColor(Color color) 549 { 550 ASS(_color == static_cast<unsigned>(COLOR_TRANSPARENT) || _color == static_cast<unsigned>(color)); 551 _color = color; 552 } // setColor 553 /** return the colour of the term */ color() const554 Color color() const { return static_cast<Color>(_color); } 555 556 bool skip() const; 557 558 /** Return true if term is an interpreted constant or contains one as its subterm */ hasInterpretedConstants() const559 bool hasInterpretedConstants() const { return _hasInterpretedConstants; } 560 /** Assign value that will be returned by the hasInterpretedConstants() function */ setInterpretedConstantsPresence(bool value)561 void setInterpretedConstantsPresence(bool value) { _hasInterpretedConstants=value; } 562 563 /** Return true if term is either an if-then-else or a let...in expression */ isSpecial() const564 bool isSpecial() const { return functor()>=SPECIAL_FUNCTOR_LOWER_BOUND; } isITE() const565 bool isITE() const { return functor() == SF_ITE; } isLet() const566 bool isLet() const { return functor() == SF_LET; } isTupleLet() const567 bool isTupleLet() const { return functor() == SF_LET_TUPLE; } isTuple() const568 bool isTuple() const { return functor() == SF_TUPLE; } isFormula() const569 bool isFormula() const { return functor() == SF_FORMULA; } 570 bool isBoolean() const; 571 /** Return pointer to structure containing extra data for special terms such as 572 * if-then-else or let...in */ getSpecialData() const573 const SpecialTermData* getSpecialData() const { return const_cast<Term*>(this)->getSpecialData(); } 574 /** Return pointer to structure containing extra data for special terms such as 575 * if-then-else or let...in */ getSpecialData()576 SpecialTermData* getSpecialData() { 577 CALL("Term::getSpecialData"); 578 ASS(isSpecial()); 579 return reinterpret_cast<SpecialTermData*>(this)-1; 580 } 581 protected: 582 vstring headToString() const; 583 584 unsigned computeDistinctVars() const; 585 586 /** 587 * Return argument order value stored in term. 588 * 589 * The default value (which is returned if no value was set using the 590 * @c setArgumentOrder() function) is zero. 591 * 592 * Currently, this function is used only by @c Ordering::getEqualityArgumentOrder(). 593 */ getArgumentOrderValue() const594 int getArgumentOrderValue() const 595 { 596 return _args[0]._info.order; 597 } 598 599 /** 600 * Store argument order value in term. 601 * 602 * The value must be non-negative and less than 8. 603 * 604 * Currently, this function is used only by @c Ordering::getEqualityArgumentOrder(). 605 */ setArgumentOrderValue(int val)606 void setArgumentOrderValue(int val) 607 { 608 CALL("Term::setArgumentOrderValue"); 609 ASS_GE(val,0); 610 ASS_L(val,8); 611 612 _args[0]._info.order = val; 613 } 614 615 #if USE_MATCH_TAG ensureMatchTag()616 inline void ensureMatchTag() 617 { 618 matchTag().ensureInit(this); 619 } 620 matchTag()621 inline MatchTag& matchTag() 622 { 623 #if ARCH_X64 624 return _args[0]._info.matchTag; 625 #else 626 return _matchTag; 627 #endif 628 } 629 630 #endif 631 632 /** For shared terms, this is a unique id used for deterministic comparison */ 633 unsigned _id; 634 /** The number of this symbol in a signature */ 635 unsigned _functor; 636 /** Arity of the symbol */ 637 unsigned _arity : 27; 638 /** colour, used in interpolation and symbol elimination */ 639 unsigned _color : 2; 640 /** Equal to 1 if the term/literal contains any interpreted constants */ 641 unsigned _hasInterpretedConstants : 1; 642 /** If true, the object is an equality literal between two variables */ 643 unsigned _isTwoVarEquality : 1; 644 /** Weight of the symbol */ 645 unsigned _weight; 646 union { 647 /** If _isTwoVarEquality is false, this value is valid and contains 648 * number of occurrences of variables */ 649 unsigned _vars; 650 /** If _isTwoVarEquality is true, this value is valid and contains 651 * the sort of the top-level variables */ 652 unsigned _sort; 653 }; 654 655 #if USE_MATCH_TAG && !ARCH_X64 656 MatchTag _matchTag; 657 #endif 658 659 /** The list of arguments or size arity+1. The first argument stores the 660 * term weight and the mask (the last two bits are 0). 661 */ 662 TermList _args[1]; 663 664 665 // /** set all boolean fields to false and weight to 0 */ 666 // void initialise() 667 // { 668 // shared = 0; 669 // ground = 0; 670 // weight = 0; 671 // } 672 // }; 673 674 // Comparison compare(const Term* t) const; 675 // void argsWeight(unsigned& total) const; 676 friend class TermList; 677 friend class MatchTag; 678 friend class Indexing::TermSharing; 679 friend class Ordering; 680 681 public: 682 /** 683 * Iterator returning arguments of a term left-to-right. 684 */ 685 class Iterator 686 { 687 public: 688 DECL_ELEMENT_TYPE(TermList); Iterator(Term * t)689 Iterator(Term* t) : _next(t->args()) {} hasNext() const690 bool hasNext() const { return _next->isNonEmpty(); } next()691 TermList next() 692 { 693 CALL("Term::Iterator::next"); 694 ASS(hasNext()); 695 TermList res = *_next; 696 _next = _next->next(); 697 return res; 698 } 699 private: 700 TermList* _next; 701 }; // Term::Iterator 702 }; // class Term 703 704 /** 705 * Class of literals. 706 * @since 06/05/2007 Manchester 707 */ 708 class Literal 709 : public Term 710 { 711 public: 712 /** True if equality literal */ isEquality() const713 bool isEquality() const 714 { return functor() == 0; } 715 716 Literal(); 717 explicit Literal(const Literal& l) throw(); 718 719 /** 720 * Create a literal. 721 * @since 16/05/2007 Manchester 722 */ Literal(unsigned functor,unsigned arity,bool polarity,bool commutative)723 Literal(unsigned functor,unsigned arity,bool polarity,bool commutative) throw() 724 { 725 _functor = functor; 726 _arity = arity; 727 _args[0]._info.polarity = polarity; 728 _args[0]._info.commutative = commutative; 729 _args[0]._info.literal = 1u; 730 } 731 732 /** 733 * A unique header, 2*p is negative and 2*p+1 if positive where p is 734 * the number of the predicate symbol. 735 */ header() const736 unsigned header() const 737 { return 2*_functor + polarity(); } 738 /** 739 * Header of the complementary literal, 2*p+1 is negative and 2*p 740 * if positive where p is the number of the predicate symbol. 741 */ complementaryHeader() const742 unsigned complementaryHeader() const 743 { return 2*_functor + 1 - polarity(); } 744 745 /** 746 * Convert header to the correponding predicate symbol number. 747 * @since 08/08/2008 flight Manchester-Singapore 748 */ headerToPredicateNumber(unsigned header)749 static unsigned int headerToPredicateNumber(unsigned header) 750 { 751 return header/2; 752 } 753 /** 754 * Convert header to the correponding polarity. 755 * @since 08/08/2008 flight Manchester-Singapore 756 */ headerToPolarity(unsigned header)757 static unsigned int headerToPolarity(unsigned header) 758 { 759 return header % 2; 760 } 761 static bool headersMatch(Literal* l1, Literal* l2, bool complementary); 762 /** Negate, should not be used with shared terms */ negate()763 void negate() 764 { 765 ASS(! shared()); 766 _args[0]._info.polarity = 1 - _args[0]._info.polarity; 767 } 768 /** set polarity to true or false */ setPolarity(bool positive)769 void setPolarity(bool positive) 770 { _args[0]._info.polarity = positive ? 1 : 0; } 771 static Literal* create(unsigned predicate, unsigned arity, bool polarity, 772 bool commutative, const TermList* args); 773 static Literal* create(Literal* l,bool polarity); 774 static Literal* create(Literal* l,TermList* args); 775 static Literal* createEquality(bool polarity, TermList arg1, TermList arg2, unsigned sort); 776 static Literal* create1(unsigned predicate, bool polarity, TermList arg); 777 static Literal* create2(unsigned predicate, bool polarity, TermList arg1, TermList arg2); 778 static Literal* create(unsigned fn, bool polarity, std::initializer_list<TermList> args); 779 780 static Literal* flattenOnArgument(const Literal*,int argumentNumber); 781 782 unsigned hash() const; 783 unsigned oppositeHash() const; 784 static Literal* complementaryLiteral(Literal* l); 785 /** If l is positive, return l; otherwise return its complementary literal. */ positiveLiteral(Literal * l)786 static Literal* positiveLiteral(Literal* l) { 787 return l->isPositive() ? l : complementaryLiteral(l); 788 } 789 /** If l is negative, return l; otherwise return its complementary literal. */ negativeLiteral(Literal * l)790 static Literal* negativeLiteral(Literal* l) { 791 return l->isNegative() ? l : complementaryLiteral(l); 792 } 793 794 /** true if positive */ isPositive() const795 bool isPositive() const 796 { 797 return _args[0]._info.polarity; 798 } // isPositive 799 800 /** true if negative */ isNegative() const801 bool isNegative() const 802 { 803 return ! _args[0]._info.polarity; 804 } // isNegative 805 806 /** return polarity, 1 if positive and 0 if negative */ polarity() const807 int polarity() const 808 { 809 return _args[0]._info.polarity; 810 } // polarity 811 812 /** 813 * Mark this object as an equality between two variables. 814 */ markTwoVarEquality()815 void markTwoVarEquality() 816 { 817 CALL("Literal::markTwoVarEquality"); 818 ASS(!shared()); 819 ASS(isEquality()); 820 ASS(nthArgument(0)->isVar() || !nthArgument(0)->term()->shared()); 821 ASS(nthArgument(1)->isVar() || !nthArgument(1)->term()->shared()); 822 823 _isTwoVarEquality = true; 824 } 825 826 827 /** Return sort of the variables in an equality between two variables. 828 * This value is set during insertion into the term sharing structure 829 */ twoVarEqSort() const830 unsigned twoVarEqSort() const 831 { 832 CALL("Literal::twoVarEqSort"); 833 ASS(isTwoVarEquality()); 834 835 return _sort; 836 } 837 838 /** Assign sort of the variables in an equality between two variables. */ setTwoVarEqSort(unsigned sort)839 void setTwoVarEqSort(unsigned sort) 840 { 841 CALL("Literal::setTwoVarEqSort"); 842 ASS(isTwoVarEquality()); 843 844 _sort = sort; 845 } 846 847 848 /** Return a new equality literal */ equality(bool polarity)849 static inline Literal* equality (bool polarity) 850 { 851 CALL("Literal::equality/1"); 852 return new(2) Literal(0,2,polarity,true); 853 } 854 855 // /** Applied @b subst to the literal and return the result */ 856 Literal* apply(Substitution& subst); 857 858 couldBeInstanceOf(Literal * lit,bool complementary)859 inline bool couldBeInstanceOf(Literal* lit, bool complementary) 860 { 861 ASS(shared()); 862 ASS(lit->shared()); 863 if(!headersMatch(this, lit, complementary)) { 864 return false; 865 } 866 return couldArgsBeInstanceOf(lit); 867 } couldArgsBeInstanceOf(Literal * lit)868 bool couldArgsBeInstanceOf(Literal* lit) 869 { 870 #if USE_MATCH_TAG 871 ensureMatchTag(); 872 lit->ensureMatchTag(); 873 if(commutative()) { 874 return matchTag().couldBeInstanceOf(lit->matchTag()) || 875 matchTag().couldBeInstanceOfReversed(lit->matchTag()); 876 } else { 877 return matchTag().couldBeInstanceOf(lit->matchTag()); 878 } 879 #else 880 return true; 881 #endif 882 } 883 884 885 886 // XMLElement toXML() const; 887 vstring toString() const; 888 const vstring& predicateName() const; 889 890 private: 891 static Literal* createVariableEquality(bool polarity, TermList arg1, TermList arg2, unsigned variableSort); 892 893 }; // class Literal 894 895 // TODO used in some proofExtra output 896 // find a better place for this? 897 bool positionIn(TermList& subterm,TermList* term, vstring& position); 898 bool positionIn(TermList& subterm,Term* term, vstring& position); 899 900 struct TermListHash { hashKernel::TermListHash901 static unsigned hash(TermList t) { 902 return static_cast<unsigned>(t.content()); 903 } 904 }; 905 906 std::ostream& operator<< (ostream& out, TermList tl ); 907 std::ostream& operator<< (ostream& out, const Term& tl ); 908 std::ostream& operator<< (ostream& out, const Literal& tl ); 909 910 }; 911 912 namespace Lib 913 { 914 915 template<> 916 struct FirstHashTypeInfo<Kernel::TermList> { 917 typedef Kernel::TermListHash Type; 918 }; 919 920 } 921 922 #endif 923