Skip to content

Commit 98684b9

Browse files
committed
TermPrinter: Guarantee unique let variable names
For a let term `(let ((l1 phi1) ... (ln phin)) psi[l1/phi1 ... ln/phin])` it must not be the case that `li` appears in `psi[l1/phi1 ... ln/phin]` as a free variable. This commit guarantees this by introducing a let prefix in `Logic` and modifying it whenever a new variable is introduced such that its name is a proper prefix of the current let prefix. The current let prefix is modified by postfixing it with a character different from the first character after the proper prefix in the new variable.
1 parent 1b6fddc commit 98684b9

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

src/common/TermPrinter.cc

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,7 @@ void TermPrinterConfig::visit(PTRef tr) {
4949
}
5050

5151
void DagPrinterConfig::visit(PTRef tr) {
52-
// Todo: Ensure that the let identifier does not also appear as a symbol
53-
auto getLetSymbol = [](PTRef tr) { return "?l" + std::to_string(tr.x); };
52+
auto getLetSymbol = [&](PTRef tr) { return logic.getLetPrefix() + std::to_string(tr.x); };
5453

5554
assert(termStrings.find(tr) == termStrings.end());
5655
Pterm const & term = logic.getPterm(tr);
@@ -71,7 +70,7 @@ void DagPrinterConfig::visit(PTRef tr) {
7170
auto const & defTerms = defsInNode->second;
7271
for (int i = defTerms.size()-1; i >= 0; i--) {
7372
// Note: Reverse order guarantees that dependencies are respected in let terms
74-
// Todo: Figure out if there is a dependency between two definitions
73+
// Todo: Use parallel lets if there is no dependency between two definitions
7574
PTRef def = defTerms[i];
7675
std::string letSymbol = getLetSymbol(def);
7776
openLetStatements += "(let ((" + letSymbol + " " + termStrings.at(def) + ")) ";

src/logics/Logic.cc

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ const char* Logic::s_sort_bool = "Bool";
5353
const char* Logic::s_ite_prefix = ".oite";
5454
const char* Logic::s_framev_prefix = ".frame";
5555
const char* Logic::s_abstract_value_prefix = "@";
56-
56+
const char Logic::c_let_var_primary_prefix = '?';
57+
const char Logic::c_let_var_secondary_prefix = 'l';
5758

5859
// The constructor initiates the base logic (Boolean)
5960
Logic::Logic(opensmt::Logic_t _logicType) :
6061
logicType(_logicType)
6162
, abstractValueCount(0)
6263
, distinctClassCount(0)
64+
, letVarPrefix(1,c_let_var_primary_prefix)
6365
, sort_store()
6466
, term_store(sym_store)
6567
, sym_IndexedSort(sort_store.newSortSymbol(SortSymbol(tk_indexed, 2, SortSymbol::INTERNAL)))
@@ -701,6 +703,12 @@ PTRef Logic::mkVar(SRef s, const char* name, bool isInterpreted) {
701703
}
702704
PTRef ptr = mkFun(sr, {});
703705
assert (ptr != PTRef_Undef);
706+
// The prefix of the names of the local variables introduced with let needs to be changed if
707+
// the current prefix is a proper prefix of the new variable's name
708+
if (letVarPrefix.size() < strlen(name) and letVarPrefix.compare(0, std::string::npos, name, letVarPrefix.size() == 0)) {
709+
char charAfterCurrentPrefix = name[letVarPrefix.size()];
710+
letVarPrefix += (charAfterCurrentPrefix != c_let_var_primary_prefix) ? c_let_var_primary_prefix : c_let_var_secondary_prefix;
711+
}
704712

705713
return ptr;
706714
}

src/logics/Logic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ class Logic {
4949
bool isKnownToUser(SymRef sr) const { return isKnownToUser(getSymName(sr)); }
5050
std::size_t abstractValueCount;
5151
int distinctClassCount;
52+
std::string letVarPrefix;
5253

5354
class DefinedFunctions {
5455
std::unordered_map<std::string,TemplateFunction> defined_functions;
@@ -147,6 +148,8 @@ class Logic {
147148
static const char* s_ite_prefix;
148149
static const char* s_framev_prefix;
149150
static const char* s_abstract_value_prefix;
151+
static const char c_let_var_primary_prefix;
152+
static const char c_let_var_secondary_prefix;
150153

151154
Logic(opensmt::Logic_t type);
152155
virtual ~Logic();
@@ -399,6 +402,7 @@ class Logic {
399402

400403
PTRef learnEqTransitivity(PTRef); // Learn limited transitivity information
401404

405+
std::string const & getLetPrefix() const { return letVarPrefix; }
402406

403407
bool hasQuotableChars(std::string const & name) const;
404408
bool isReservedWord(std::string const & name) const;

0 commit comments

Comments
 (0)