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