1 
2 /*
3  * File Signature.cpp.
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 Signature.cpp
21  * Implements class Signature for handling signatures
22  */
23 
24 #include "Lib/Environment.hpp"
25 #include "Lib/Int.hpp"
26 #include "Shell/Options.hpp"
27 #include "Shell/DistinctGroupExpansion.hpp"
28 
29 #include "Signature.hpp"
30 
31 using namespace std;
32 using namespace Kernel;
33 using namespace Shell;
34 
35 const unsigned Signature::STRING_DISTINCT_GROUP = 0;
36 
37 /**
38  * Standard constructor.
39  * @since 03/05/2013 train London-Manchester, argument numericConstant added
40  * @author Andrei Voronkov
41  */
Symbol(const vstring & nm,unsigned arity,bool interpreted,bool stringConstant,bool numericConstant,bool overflownConstant)42 Signature::Symbol::Symbol(const vstring& nm,unsigned arity, bool interpreted, bool stringConstant,bool numericConstant, bool overflownConstant)
43   : _name(nm),
44     _arity(arity),
45     _interpreted(interpreted ? 1 : 0),
46     _introduced(0),
47     _protected(0),
48     _skip(0),
49     _label(0),
50     _equalityProxy(0),
51     _color(COLOR_TRANSPARENT),
52     _stringConstant(stringConstant ? 1: 0),
53     _numericConstant(numericConstant ? 1: 0),
54     _answerPredicate(0),
55     _overflownConstant(overflownConstant ? 1 : 0),
56     _termAlgebraCons(0),
57     _type(0),
58     _distinctGroups(0),
59     _usageCount(0),
60     _unitUsageCount(0),
61     _inGoal(0),
62     _inUnit(0),
63     _inductionSkolem(0),
64     _skolem(0)
65 {
66   CALL("Signature::Symbol::Symbol");
67   ASS(!stringConstant || arity==0);
68 
69   if (!stringConstant && !numericConstant && !overflownConstant && symbolNeedsQuoting(_name, interpreted,arity)) {
70     _name="'"+_name+"'";
71   }
72   if (_interpreted || isProtectedName(nm)) {
73     markProtected();
74   }
75 } // Symbol::Symbol
76 
77 /**
78  * Deallocate function Symbol object
79  */
destroyFnSymbol()80 void Signature::Symbol::destroyFnSymbol()
81 {
82   CALL("Signature::Symbol::destroyFnSymbol");
83 
84   if (integerConstant()) {
85     delete static_cast<IntegerSymbol*>(this);
86   }
87   else if (rationalConstant()) {
88     delete static_cast<RationalSymbol*>(this);
89   }
90   else if (realConstant()) {
91     delete static_cast<RealSymbol*>(this);
92   }
93   else if (interpreted()) {
94     delete static_cast<InterpretedSymbol*>(this);
95   }
96   else {
97     delete this;
98   }
99 }
100 
101 /**
102  * Deallocate predicate Symbol object
103  */
destroyPredSymbol()104 void Signature::Symbol::destroyPredSymbol()
105 {
106   CALL("Signature::Symbol::destroyPredSymbol");
107 
108   if (interpreted()) {
109     delete static_cast<InterpretedSymbol*>(this);
110   }
111   else {
112     delete this;
113   }
114 }
115 
116 /**
117  * Add constant symbol into a distinct group
118  *
119  * A constant can be added into one particular distinct group
120  * at most once
121  *
122  * We also record the symbol in the group's members, under certain conditions
123  */
addToDistinctGroup(unsigned group,unsigned this_number)124 void Signature::Symbol::addToDistinctGroup(unsigned group,unsigned this_number)
125 {
126   CALL("Signature::Symbol::addToDistinctGroup");
127 
128   ASS_EQ(arity(), 0);
129   ASS(!List<unsigned>::member(group, _distinctGroups))
130 
131   List<unsigned>::push(group, _distinctGroups);
132 
133   env.signature->_distinctGroupsAddedTo=true;
134 
135   Signature::DistinctGroupMembers members = env.signature->_distinctGroupMembers[group];
136   if(members->size() <= DistinctGroupExpansion::EXPAND_UP_TO_SIZE || env.options->bfnt()
137                        || env.options->saturationAlgorithm()==Options::SaturationAlgorithm::FINITE_MODEL_BUILDING){
138     // we add one more than EXPAND_UP_TO_SIZE to signal to DistinctGroupExpansion::apply not to expand
139     // ... instead DistinctEqualitySimplifier will take over
140     members->push(this_number);
141   }
142 
143 } // addToDistinctGroup
144 
145 /**
146  * Set type of the symbol
147  *
148  * The type can be set only once for each symbol, and if the type
149  * should be different from the default type, this function must be
150  * called before any call to @c fnType() or @c predType().
151  */
setType(OperatorType * type)152 void Signature::Symbol::setType(OperatorType* type)
153 {
154   CALL("Signature::Symbol::setType");
155   ASS(!_type);
156 
157   _type = type;
158 }
159 
160 /**
161  * This force the type to change
162  * This can be unsafe so should only be used when you know it is safe to
163  * change the type i.e. nothing yet relies on the type of this symbol
164  */
forceType(OperatorType * type)165 void Signature::Symbol::forceType(OperatorType* type)
166 {
167   CALL("Signature::Symbol::forceType");
168   if(_type){ delete _type; }
169   _type = type;
170 }
171 
172 /**
173  * Return the type of a function symbol
174  *
175  * If the @c setType() function was not called before, the function
176  * symbol is assigned a default type.
177  */
fnType() const178 OperatorType* Signature::Symbol::fnType() const
179 {
180   CALL("Signature::Symbol::fnType");
181 
182   if (!_type) {
183     _type = OperatorType::getFunctionType(arity(), (unsigned*)0, Sorts::SRT_DEFAULT);
184   }
185   return _type;
186 }
187 
188 /**
189  * Return the type of a predicate symbol
190  *
191  * If the @c setType() function was not called before, the function
192  * symbol is assigned a default type.
193  */
predType() const194 OperatorType* Signature::Symbol::predType() const
195 {
196   CALL("Signature::Symbol::predType");
197 
198   if (!_type) {
199     _type = OperatorType::getPredicateType(arity(), (unsigned*)0);
200   }
201   return _type;
202 }
203 
204 
205 /**
206  * Create a Signature.
207  * @since 07/05/2007 Manchester
208  * @since 04/05/2015 Gothenburg -- add true and false
209  */
Signature()210 Signature::Signature ():
211     _foolConstantsDefined(false), _foolTrue(0), _foolFalse(0),
212     _funs(32),
213     _preds(32),
214     _nextFreshSymbolNumber(0),
215     _skolemFunctionCount(0),
216     _distinctGroupsAddedTo(false),
217     _strings(0),
218     _integers(0),
219     _rationals(0),
220     _reals(0),
221     _termAlgebras()
222 {
223   CALL("Signature::Signature");
224 
225   // initialize equality
226   addInterpretedPredicate(Theory::EQUAL, OperatorType::getPredicateType(2), "=");
227   ASS_EQ(predicateName(0), "="); //equality must have number 0
228   getPredicate(0)->markSkip();
229 
230   unsigned aux;
231   aux = createDistinctGroup();
232   ASS_EQ(STRING_DISTINCT_GROUP, aux);
233 } // Signature::Signature
234 
235 /**
236  * Destroy a Signature.
237  * @since 07/05/2007 Manchester
238  */
~Signature()239 Signature::~Signature ()
240 {
241   for (int i = _funs.length()-1;i >= 0;i--) {
242     _funs[i]->destroyFnSymbol();
243   }
244   for (int i = _preds.length()-1;i >= 0;i--) {
245     _preds[i]->destroyPredSymbol();
246   }
247 } // Signature::~Signature
248 
249 /**
250  * Add an integer constant to the signature. If defaultSort is true, treat it as
251  * a term of the default sort, otherwise as an interepreted integer value.
252  * @since 03/05/2013 train Manchester-London
253  * @author Andrei Voronkov
254  */
addIntegerConstant(const vstring & number,bool defaultSort)255 unsigned Signature::addIntegerConstant(const vstring& number,bool defaultSort)
256 {
257   CALL("Signature::addIntegerConstant(vstring)");
258 
259   IntegerConstantType value(number);
260   if (!defaultSort) {
261     return addIntegerConstant(value);
262   }
263 
264   // default sort should be used
265   vstring name = value.toString();
266   vstring symbolKey = name + "_n";
267   unsigned result;
268   if (_funNames.find(symbolKey,result)) {
269     return result;
270   }
271 
272   result = _funs.length();
273   Symbol* sym = new Symbol(name,0,false,false,true);
274   /*
275   sym->addToDistinctGroup(INTEGER_DISTINCT_GROUP,result);
276   if(defaultSort){
277      sym->addToDistinctGroup(STRING_DISTINCT_GROUP,result); // numbers are disctinct from strings
278   }
279   */
280   _funs.push(sym);
281   _funNames.insert(symbolKey,result);
282   return result;
283 } // Signature::addIntegerConstant
284 
285 /**
286  * Add an integer constant to the signature.
287  * @todo something smarter, so that we don't need to convert all values to string
288  */
addIntegerConstant(const IntegerConstantType & value)289 unsigned Signature::addIntegerConstant(const IntegerConstantType& value)
290 {
291   CALL("Signature::addIntegerConstant");
292 
293   vstring key = value.toString() + "_n";
294   unsigned result;
295   if (_funNames.find(key, result)) {
296     return result;
297   }
298   _integers++;
299   result = _funs.length();
300   Symbol* sym = new IntegerSymbol(value);
301   _funs.push(sym);
302   _funNames.insert(key,result);
303   /*
304   sym->addToDistinctGroup(INTEGER_DISTINCT_GROUP,result);
305   */
306   return result;
307 } // addIntegerConstant
308 
309 /**
310  * Add a rational constant to the signature. If defaultSort is true, treat it as
311  * a term of the default sort, otherwise as an interepreted rational value.
312  * @since 03/05/2013 London
313  * @author Andrei Voronkov
314  */
addRationalConstant(const vstring & numerator,const vstring & denominator,bool defaultSort)315 unsigned Signature::addRationalConstant(const vstring& numerator, const vstring& denominator,bool defaultSort)
316 {
317   CALL("Signature::addRationalConstant(vstring,vstring)");
318 
319   RationalConstantType value(numerator, denominator);
320   if (!defaultSort) {
321     return addRationalConstant(value);
322   }
323 
324   vstring name = value.toString();
325   vstring key = name + "_q";
326   unsigned result;
327   if (_funNames.find(key,result)) {
328     return result;
329   }
330   result = _funs.length();
331   Symbol* sym = new Symbol(name,0,false,false,true);
332   /*
333   if(defaultSort){
334     sym->addToDistinctGroup(STRING_DISTINCT_GROUP,result); // numbers are distinct from strings
335   }
336   sym->addToDistinctGroup(RATIONAL_DISTINCT_GROUP,result);
337   */
338   _funs.push(sym);
339   _funNames.insert(key,result);
340   return result;
341 } // addRatonalConstant
342 
addRationalConstant(const RationalConstantType & value)343 unsigned Signature::addRationalConstant(const RationalConstantType& value)
344 {
345   CALL("Signature::addRationalConstant");
346 
347   vstring key = value.toString() + "_q";
348   unsigned result;
349   if (_funNames.find(key, result)) {
350     return result;
351   }
352   _rationals++;
353   result = _funs.length();
354   _funs.push(new RationalSymbol(value));
355   _funNames.insert(key, result);
356   return result;
357 } // Signature::addRationalConstant
358 
359 /**
360  * Add a real constant to the signature. If defaultSort is true, treat it as
361  * a term of the default sort, otherwise as an interepreted real value.
362  * @since 03/05/2013 London
363  * @author Andrei Voronkov
364  */
addRealConstant(const vstring & number,bool defaultSort)365 unsigned Signature::addRealConstant(const vstring& number,bool defaultSort)
366 {
367   CALL("Signature::addRealConstant(vstring)");
368 
369   RealConstantType value(number);
370   if (!defaultSort) {
371     return addRealConstant(value);
372   }
373   vstring key = value.toString() + "_r";
374   unsigned result;
375   if (_funNames.find(key,result)) {
376     return result;
377   }
378   result = _funs.length();
379   Symbol* sym = new Symbol(value.toNiceString(),0,false,false,true);
380   /*
381   if(defaultSort){
382     sym->addToDistinctGroup(STRING_DISTINCT_GROUP,result); // numbers are distinct from strings
383   }
384   sym->addToDistinctGroup(REAL_DISTINCT_GROUP,result);
385   */
386   _funs.push(sym);
387   _funNames.insert(key,result);
388   return result;
389 } // addRealConstant
390 
addRealConstant(const RealConstantType & value)391 unsigned Signature::addRealConstant(const RealConstantType& value)
392 {
393   CALL("Signature::addRealConstant");
394 
395   vstring key = value.toString() + "_r";
396   unsigned result;
397   if (_funNames.find(key, result)) {
398     return result;
399   }
400   _reals++;
401   result = _funs.length();
402   _funs.push(new RealSymbol(value));
403   _funNames.insert(key, result);
404   return result;
405 }
406 
407 /**
408  * Add interpreted function
409  */
addInterpretedFunction(Interpretation interpretation,OperatorType * type,const vstring & name)410 unsigned Signature::addInterpretedFunction(Interpretation interpretation, OperatorType* type, const vstring& name)
411 {
412   CALL("Signature::addInterpretedFunction(Interpretation,OperatorType*,const vstring&)");
413   ASS(Theory::isFunction(interpretation));
414 
415   Theory::MonomorphisedInterpretation mi = std::make_pair(interpretation,type);
416 
417   unsigned res;
418   if (_iSymbols.find(mi,res)) { // already declared
419     if (name!=functionName(res)) {
420       USER_ERROR("Interpreted function '"+functionName(res)+"' has the same interpretation as '"+name+"' should have");
421     }
422     return res;
423   }
424 
425   vstring symbolKey = name+"_i"+Int::toString(interpretation)+(Theory::isPolymorphic(interpretation) ? type->toString() : "");
426   ASS(!_funNames.find(symbolKey));
427 
428   unsigned fnNum = _funs.length();
429   InterpretedSymbol* sym = new InterpretedSymbol(name, interpretation);
430   _funs.push(sym);
431   _funNames.insert(symbolKey, fnNum);
432   ALWAYS(_iSymbols.insert(mi, fnNum));
433 
434   OperatorType* fnType = type;
435   ASS(fnType->isFunctionType());
436   sym->setType(fnType);
437   return fnNum;
438 } // Signature::addInterpretedFunction
439 
440 /**
441  * Add interpreted predicate
442  */
addInterpretedPredicate(Interpretation interpretation,OperatorType * type,const vstring & name)443 unsigned Signature::addInterpretedPredicate(Interpretation interpretation, OperatorType* type, const vstring& name)
444 {
445   CALL("Signature::addInterpretedPredicate(Interpretation,OperatorType*,const vstring&)");
446   ASS(!Theory::isFunction(interpretation));
447 
448   // cout << "addInterpretedPredicate " << (type ? type->toString() : "nullptr") << " " << name << endl;
449 
450   Theory::MonomorphisedInterpretation mi = std::make_pair(interpretation,type);
451 
452   unsigned res;
453   if (_iSymbols.find(mi,res)) { // already declared
454     if (name!=predicateName(res)) {
455       USER_ERROR("Interpreted predicate '"+predicateName(res)+"' has the same interpretation as '"+name+"' should have");
456     }
457     return res;
458   }
459 
460   vstring symbolKey = name+"_i"+Int::toString(interpretation)+(Theory::isPolymorphic(interpretation) ? type->toString() : "");
461 
462   // cout << "symbolKey " << symbolKey << endl;
463 
464   ASS(!_predNames.find(symbolKey));
465 
466   unsigned predNum = _preds.length();
467   InterpretedSymbol* sym = new InterpretedSymbol(name, interpretation);
468   _preds.push(sym);
469   _predNames.insert(symbolKey,predNum);
470   ALWAYS(_iSymbols.insert(mi, predNum));
471   if (predNum!=0) {
472     OperatorType* predType = type;
473     ASS_REP(!predType->isFunctionType(), predType->toString());
474     sym->setType(predType);
475   }
476   return predNum;
477 } // Signature::addInterpretedPredicate
478 
479 
480 /**
481  * Return number of symbol that is interpreted by Interpretation @b interp.
482  *
483  * If no such symbol exists, it is created.
484  */
getInterpretingSymbol(Interpretation interp,OperatorType * type)485 unsigned Signature::getInterpretingSymbol(Interpretation interp, OperatorType* type)
486 {
487   CALL("Signature::getInterpretingSymbol(Interpretation,OperatorType*)");
488 
489   Theory::MonomorphisedInterpretation mi = std::make_pair(interp,type);
490 
491   unsigned res;
492   if (_iSymbols.find(mi, res)) {
493     return res;
494   }
495 
496   vstring name = theory->getInterpretationName(interp);
497   unsigned arity = Theory::getArity(interp);
498 
499   if (Theory::isFunction(interp)) {
500     if (functionExists(name, arity)) {
501       int i=0;
502       while(functionExists(name+Int::toString(i), arity)) {
503         i++;
504       }
505       name=name+Int::toString(i);
506     }
507     addInterpretedFunction(interp, type, name);
508   }
509   else {
510     if (predicateExists(name, arity)) {
511       int i=0;
512       while(predicateExists(name+Int::toString(i), arity)) {
513         i++;
514       }
515       name=name+Int::toString(i);
516     }
517     addInterpretedPredicate(interp, type, name);
518   }
519 
520   //we have now registered a new function, so it should be present in the map
521   return _iSymbols.get(mi);
522 }
523 
functionName(int number)524 const vstring& Signature::functionName(int number)
525 {
526   CALL("Signature::functionName");
527 
528   // it is safe to reuse "$true" and "$false" for constants
529   // because the user cannot define constants with these names herself
530   // and the formula, obtained by toString() with "$true" or "$false"
531   // in term position would be syntactically valid in FOOL
532   if (!env.options->showFOOL() && isFoolConstantSymbol(false,number)) {
533     static vstring fols("$false");
534     return fols;
535   }
536   if (!env.options->showFOOL() && isFoolConstantSymbol(true,number)) {
537     static vstring troo("$true");
538     return troo;
539   }
540   return _funs[number]->name();
541 }
542 
543 /**
544  * Return true if specified function exists
545  */
functionExists(const vstring & name,unsigned arity) const546 bool Signature::functionExists(const vstring& name,unsigned arity) const
547 {
548   CALL("Signature::functionExists");
549 
550   return _funNames.find(key(name, arity));
551 }
552 
553 /**
554  * Return true if specified predicate exists
555  */
predicateExists(const vstring & name,unsigned arity) const556 bool Signature::predicateExists(const vstring& name,unsigned arity) const
557 {
558   CALL("Signature::predicateExists");
559 
560   return _predNames.find(key(name, arity));
561 }
562 
getFunctionNumber(const vstring & name,unsigned arity) const563 unsigned Signature::getFunctionNumber(const vstring& name, unsigned arity) const
564 {
565   CALL("Signature::getFunctionNumber");
566 
567   ASS(_funNames.find(key(name, arity)));
568   return _funNames.get(key(name, arity));
569 }
570 
getPredicateNumber(const vstring & name,unsigned arity) const571 unsigned Signature::getPredicateNumber(const vstring& name, unsigned arity) const
572 {
573   CALL("Signature::getPredicateNumber");
574 
575   ASS(_predNames.find(key(name, arity)));
576   return _predNames.get(key(name, arity));
577 }
578 
579 /**
580  * If a function with this name and arity exists, return its number.
581  * Otherwise, add a new one and return its number.
582  *
583  * @param name name of the symbol
584  * @param arity arity of the symbol
585  * @param added will be set to true if the function did not exist
586  * @since 07/05/2007 Manchester
587  */
addFunction(const vstring & name,unsigned arity,bool & added,bool overflowConstant)588 unsigned Signature::addFunction (const vstring& name,
589 				 unsigned arity,
590 				 bool& added,
591 				 bool overflowConstant)
592 {
593   CALL("Signature::addFunction");
594 
595   vstring symbolKey = key(name,arity);
596   unsigned result;
597   if (_funNames.find(symbolKey,result)) {
598     added = false;
599     getFunction(result)->unmarkIntroduced();
600     return result;
601   }
602   if (env.options->arityCheck()) {
603     unsigned prev;
604     if (_arityCheck.find(name,prev)) {
605       unsigned prevArity = prev/2;
606       bool isFun = prev % 2;
607       USER_ERROR((vstring)"Symbol " + name +
608 		 " is used both as a function of arity " + Int::toString(arity) +
609 		 " and a " + (isFun ? "function" : "predicate") +
610 		 " of arity " + Int::toString(prevArity));
611     }
612     _arityCheck.insert(name,2*arity+1);
613   }
614 
615   result = _funs.length();
616   _funs.push(new Symbol(name, arity, false, false, false, overflowConstant));
617   _funNames.insert(symbolKey, result);
618   added = true;
619   return result;
620 } // Signature::addFunction
621 
622 /**
623  * Add a string constant to the signature. This constant will automatically be
624  * added to the distinct group STRING_DISTINCT_GROUP.
625  * @author Andrei Voronkov
626  */
addStringConstant(const vstring & name)627 unsigned Signature::addStringConstant(const vstring& name)
628 {
629   CALL("Signature::addStringConstant");
630 
631   vstring symbolKey = name + "_c";
632   unsigned result;
633   if (_funNames.find(symbolKey,result)) {
634     return result;
635   }
636 
637   _strings++;
638   vstring quotedName = "\"" + name + "\"";
639   result = _funs.length();
640   Symbol* sym = new Symbol(quotedName,0,false,true);
641   sym->addToDistinctGroup(STRING_DISTINCT_GROUP,result);
642   _funs.push(sym);
643   _funNames.insert(symbolKey,result);
644   return result;
645 } // addStringConstant
646 
647 /**
648  * If a predicate with this name and arity exists, return its number.
649  * Otherwise, add a new one and return its number.
650  *
651  * @param name name of the symbol
652  * @param arity arity of the symbol
653  * @param added set to true if a new predicate has been added, and false
654  *        otherwise
655  * @since 07/05/2007 Manchester
656  * @since 08/07/2007 Manchester, adds parameter added
657  * @since 06/12/2009 Haifa, arity check added
658  * @author Andrei Voronkov
659  */
addPredicate(const vstring & name,unsigned arity,bool & added)660 unsigned Signature::addPredicate (const vstring& name,
661 				  unsigned arity,
662 				  bool& added)
663 {
664   CALL("Signature::addPredicate");
665 
666   vstring symbolKey = key(name,arity);
667   unsigned result;
668   if (_predNames.find(symbolKey,result)) {
669     added = false;
670     getPredicate(result)->unmarkIntroduced();
671     return result;
672   }
673   if (env.options->arityCheck()) {
674     unsigned prev;
675     if (_arityCheck.find(name,prev)) {
676       unsigned prevArity = prev/2;
677       bool isFun = prev % 2;
678       USER_ERROR((vstring)"Symbol " + name +
679 		 " is used both as a predicate of arity " + Int::toString(arity) +
680 		 " and a " + (isFun ? "function" : "predicate") +
681 		 " of arity " + Int::toString(prevArity));
682     }
683     _arityCheck.insert(name,2*arity);
684   }
685 
686   result = _preds.length();
687   _preds.push(new Symbol(name,arity));
688   _predNames.insert(symbolKey,result);
689   added = true;
690   return result;
691 } // Signature::addPredicate
692 
693 /**
694  * Create a new name.
695  * @since 01/07/2005 Manchester
696  */
addNamePredicate(unsigned arity)697 unsigned Signature::addNamePredicate(unsigned arity)
698 {
699   CALL("Signature::addNamePredicate");
700   return addFreshPredicate(arity,"sP");
701 } // addNamePredicate
702 
703 /**
704  * Add fresh function of a given arity and with a given prefix. If suffix is non-zero,
705  * the function name will be prefixI, where I is an integer, otherwise it will be
706  * prefixI_suffix. The new function will be marked as skip for the purpose of equality
707  * elimination.
708  */
addFreshFunction(unsigned arity,const char * prefix,const char * suffix)709 unsigned Signature::addFreshFunction(unsigned arity, const char* prefix, const char* suffix)
710 {
711   CALL("Signature::addFreshFunction");
712 
713   vstring pref(prefix);
714   vstring suf(suffix ? vstring("_")+suffix : "");
715   bool added;
716   unsigned result;
717   //commented out because it could lead to introduction of function with the same name
718   //that differ only in arity (which is OK with tptp, but iProver was complaining when
719   //using Vampire as clausifier)
720 //  unsigned result = addFunction(pref+suf,arity,added);
721 //  if (!added) {
722     do {
723       result = addFunction(pref+Int::toString(_nextFreshSymbolNumber++)+suf,arity,added);
724     }
725     while (!added);
726 //  }
727   Symbol* sym = getFunction(result);
728   sym->markIntroduced();
729   sym->markSkip();
730   return result;
731 } // addFreshFunction
732 
733 /**
734  * Add fresh predicate of a given arity and with a given prefix. If suffix is non-zero,
735  * the predicate name will be prefixI, where I is an integer, otherwise it will be
736  * prefixI_suffix. The new predicate will be marked as skip for the purpose of equality
737  * elimination.
738  */
addFreshPredicate(unsigned arity,const char * prefix,const char * suffix)739 unsigned Signature::addFreshPredicate(unsigned arity, const char* prefix, const char* suffix)
740 {
741   CALL("Signature::addFreshPredicate");
742 
743   vstring pref(prefix);
744   vstring suf(suffix ? vstring("_")+suffix : "");
745   bool added = false;
746   unsigned result;
747   //commented out because it could lead to introduction of function with the same name
748   //that differ only in arity (which is OK with tptp, but iProver was complaining when
749   //using Vampire as clausifier)
750 //  if (suffix) {
751 //    result = addPredicate(pref+suf,arity,added);
752 //  }
753 //  if (!added) {
754     do {
755       result = addPredicate(pref+Int::toString(_nextFreshSymbolNumber++)+suf,arity,added);
756     }
757     while (!added);
758 //  }
759   Symbol* sym = getPredicate(result);
760   sym->markIntroduced();
761   sym->markSkip();
762   return result;
763 } // addFreshPredicate
764 
765 /**
766  * Return a new Skolem function. If @b suffix is nonzero, include it
767  * into the name of the Skolem function.
768  * @since 01/07/2005 Manchester
769  */
addSkolemFunction(unsigned arity,const char * suffix)770 unsigned Signature::addSkolemFunction (unsigned arity, const char* suffix)
771 {
772   CALL("Signature::addSkolemFunction");
773 
774   unsigned f = addFreshFunction(arity, "sK", suffix);
775   getFunction(f)->markSkolem();
776 
777   // Register it as a LaTeX function
778   theory->registerLaTeXFuncName(f,"\\sigma_{"+Int::toString(_skolemFunctionCount)+"}(a0)");
779   _skolemFunctionCount++;
780 
781   return f;
782 } // addSkolemFunction
783 
784 /**
785  * Return a new Skolem predicate. If @b suffix is nonzero, include it
786  * into the name of the Skolem function.
787  * @since 15/02/2016 Gothenburg
788  */
addSkolemPredicate(unsigned arity,const char * suffix)789 unsigned Signature::addSkolemPredicate(unsigned arity, const char* suffix)
790 {
791   CALL("Signature::addSkolemPredicate");
792 
793   unsigned f = addFreshPredicate(arity, "sK", suffix);
794   getPredicate(f)->markSkolem();
795 
796   // Register it as a LaTeX function
797   theory->registerLaTeXFuncName(f,"\\sigma_{"+Int::toString(_skolemFunctionCount)+"}(a0)");
798   _skolemFunctionCount++;
799 
800   return f;
801 } // addSkolemPredicate
802 
803 /**
804  * Return the key "name_arity" used for hashing. This key is obtained by
805  * concatenating the name, underscore character and the arity. The key is
806  * created in such a way that it does not collide with special keys, such as
807  * those for string constants.
808  * @since 27/02/2006 Redmond
809  * @author Andrei Voronkov
810  */
key(const vstring & name,int arity)811 vstring Signature::key(const vstring& name,int arity)
812 {
813   return name + '_' + Int::toString(arity);
814 } // Signature::key
815 
816 
817 /** Add a color to the symbol for interpolation and symbol elimination purposes */
addColor(Color color)818 void Signature::Symbol::addColor(Color color)
819 {
820   ASS_L(color,3);
821   ASS_G(color,0);
822   ASS(env.colorUsed);
823 
824   if (_color && color != static_cast<Color>(_color)) {
825     USER_ERROR("A symbol cannot have two colors");
826   }
827   _color = color;
828 } // addColor
829 
830 /**
831  * Create a group of distinct elements. @c premise should contain
832  * the unit that declared the distinct group, or zero if there isn't any.
833  */
createDistinctGroup(Unit * premise)834 unsigned Signature::createDistinctGroup(Unit* premise)
835 {
836   CALL("Signature::createDistinctGroup");
837 
838   unsigned res = _distinctGroupPremises.size();
839   _distinctGroupPremises.push(premise);
840   // DistinctGroupMember stack = ;
841   _distinctGroupMembers.push(DistinctGroupMembers(new Stack<unsigned>));
842   return res;
843 }
844 
845 /**
846  * Return premise of the distinct group, or 0 if the distinct group doesn't have any
847  */
getDistinctGroupPremise(unsigned group)848 Unit* Signature::getDistinctGroupPremise(unsigned group)
849 {
850   CALL("Signature::getDistinctGroupPremise");
851 
852   return _distinctGroupPremises[group];
853 }
854 
855 /**
856  * Add a constant into a group of distinct elements
857  *
858  * One constant can be added into one particular distinct group only once.
859  */
addToDistinctGroup(unsigned constantSymbol,unsigned groupId)860 void Signature::addToDistinctGroup(unsigned constantSymbol, unsigned groupId)
861 {
862   CALL("Signature::addToDistinctGroup");
863 
864   Symbol* sym = getFunction(constantSymbol);
865   sym->addToDistinctGroup(groupId,constantSymbol);
866 }
867 
isProtectedName(vstring name)868 bool Signature::isProtectedName(vstring name)
869 {
870   CALL("Signature::isProtectedName");
871 
872   if (name=="$distinct") {
873     //TODO: remove this hack once we properly support the $distinct predicate
874     return true;
875   }
876 
877   vstring protectedPrefix = env.options->protectedPrefix();
878   if (protectedPrefix.size()==0) {
879     return false;
880   }
881   if (name.substr(0, protectedPrefix.size())==protectedPrefix) {
882     return true;
883   }
884   return false;
885 }
886 
887 /**
888  * Return true if specified symbol should be quoted in the TPTP syntax.
889  * This function does not apply to integer or string constants. It only
890  * applies during parsing, it is not used when the symbol is printed:
891  * when it is printed, its saved name will already be quoted.
892  *
893  * The function charNeedsQuoting determines characters whose presence in
894  * the symbol name implies that they should be quoted. There are however
895  * several exceptions to it:
896  *
897  * Equality is not quoted
898  *
899  * Numbers are not quoted. However names that just look like numbers
900  * are quoted (the distinction is that these are not interpreted)
901  *
902  * $distinct predicate is not quoted
903  *
904  * $true and $false -- the names of FOOL term-level boolean constants are not quoted
905  *
906  * For interpreted symbols its legal to start with $
907  *
908  * It's legal for symbols to start with $$.
909  *
910  * @since 03/05/2013 train Manchester-London
911  * @since 04/05/2015 Gothenburg -- do not quote FOOL true and false
912  */
symbolNeedsQuoting(vstring name,bool interpreted,unsigned arity)913 bool Signature::symbolNeedsQuoting(vstring name, bool interpreted, unsigned arity)
914 {
915   CALL("Signature::symbolNeedsQuoting");
916   ASS_G(name.length(),0);
917 
918   if (name=="=" || (interpreted && arity==0)) {
919     return false;
920   }
921 
922   const char* c = name.c_str();
923   bool quote = false;
924   bool first = true;
925   if (*c=='$') {
926     if (*(c+1)=='$') {
927       c+=2; //skip the initial $$
928       first = false;
929     }
930     else if (interpreted) {
931       c++; //skip the initial $ for interpreted
932       first = false;
933     }
934   }
935   while(!quote && *c) {
936     quote |= charNeedsQuoting(*c, first);
937     first = false;
938     c++;
939   }
940   if (!quote) { return false; }
941   if (name=="$distinct") {
942     //TODO: remove this once we properly support the $distinct predicate and quoting
943     return false;
944   }
945   if (name.find("$array") == 0) {
946     //TODO: a hacky solution not to quote array sorts
947     return false;
948   }
949   return true;
950 } // Signature::symbolNeedsQuoting
951 
getTermAlgebraConstructor(unsigned functor)952 TermAlgebraConstructor* Signature::getTermAlgebraConstructor(unsigned functor)
953 {
954   CALL("Signature::getTermAlgebraConstructor");
955 
956   if (getFunction(functor)->termAlgebraCons()) {
957     TermAlgebra *ta = _termAlgebras.get(getFunction(functor)->fnType()->result());
958     if (ta) {
959       for (unsigned i = 0; i < ta->nConstructors(); i++) {
960         TermAlgebraConstructor *c = ta->constructor(i);
961         if (c->functor() == functor)
962           return c;
963       }
964     }
965   }
966 
967   return nullptr;
968 }
969 
970 /**
971  * Return true if the name containing che character must be quoted
972  */
charNeedsQuoting(char c,bool first)973 bool Signature::charNeedsQuoting(char c, bool first)
974 {
975   switch (c) {
976   case 'a':
977   case 'b':
978   case 'c':
979   case 'd':
980   case 'e':
981   case 'f':
982   case 'g':
983   case 'h':
984   case 'i':
985   case 'j':
986   case 'k':
987   case 'l':
988   case 'm':
989   case 'n':
990   case 'o':
991   case 'p':
992   case 'q':
993   case 'r':
994   case 's':
995   case 't':
996   case 'u':
997   case 'v':
998   case 'w':
999   case 'x':
1000   case 'y':
1001   case 'z':
1002 //  case '$':
1003     return false;
1004   case 'A':
1005   case 'B':
1006   case 'C':
1007   case 'D':
1008   case 'E':
1009   case 'F':
1010   case 'G':
1011   case 'H':
1012   case 'I':
1013   case 'J':
1014   case 'K':
1015   case 'L':
1016   case 'M':
1017   case 'N':
1018   case 'O':
1019   case 'P':
1020   case 'Q':
1021   case 'R':
1022   case 'S':
1023   case 'T':
1024   case 'U':
1025   case 'V':
1026   case 'W':
1027   case 'X':
1028   case 'Y':
1029   case 'Z':
1030   case '_':
1031   case '0':
1032   case '1':
1033   case '2':
1034   case '3':
1035   case '4':
1036   case '5':
1037   case '6':
1038   case '7':
1039   case '8':
1040   case '9':
1041     return first;
1042   default:
1043     return true;
1044   }
1045 }
1046