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