GCC Code Coverage Report
Directory: . Exec Total Coverage
File: src/expr/symbol_manager.cpp Lines: 144 149 96.6 %
Date: 2021-05-22 Branches: 127 236 53.8 %

Line Exec Source
1
/******************************************************************************
2
 * Top contributors (to current version):
3
 *   Andrew Reynolds, Aina Niemetz
4
 *
5
 * This file is part of the cvc5 project.
6
 *
7
 * Copyright (c) 2009-2021 by the authors listed in the file AUTHORS
8
 * in the top-level source directory and their institutional affiliations.
9
 * All rights reserved.  See the file COPYING in the top-level source
10
 * directory for licensing information.
11
 * ****************************************************************************
12
 *
13
 * The symbol manager.
14
 */
15
16
#include "expr/symbol_manager.h"
17
18
#include "context/cdhashmap.h"
19
#include "context/cdhashset.h"
20
#include "context/cdlist.h"
21
#include "context/cdo.h"
22
23
using namespace cvc5::context;
24
25
namespace cvc5 {
26
27
// ---------------------------------------------- SymbolManager::Implementation
28
29
class SymbolManager::Implementation
30
{
31
  using TermStringMap = CDHashMap<api::Term, std::string, std::hash<api::Term>>;
32
  using TermSet = CDHashSet<api::Term, std::hash<api::Term>>;
33
  using SortList = CDList<api::Sort>;
34
  using TermList = CDList<api::Term>;
35
36
 public:
37
6145
  Implementation()
38
6145
      : d_context(),
39
        d_names(&d_context),
40
        d_namedAsserts(&d_context),
41
        d_declareSorts(&d_context),
42
        d_declareTerms(&d_context),
43
        d_funToSynth(&d_context),
44
6145
        d_hasPushedScope(&d_context, false)
45
  {
46
    // use an outermost push, to be able to clear all definitions
47
6145
    d_context.push();
48
6145
  }
49
50
6145
  ~Implementation() { d_context.pop(); }
51
  /** set expression name */
52
  NamingResult setExpressionName(api::Term t,
53
                                 const std::string& name,
54
                                 bool isAssertion = false);
55
  /** get expression name */
56
  bool getExpressionName(api::Term t,
57
                         std::string& name,
58
                         bool isAssertion = false) const;
59
  /** get expression names */
60
  void getExpressionNames(const std::vector<api::Term>& ts,
61
                          std::vector<std::string>& names,
62
                          bool areAssertions = false) const;
63
  /** get expression names */
64
  std::map<api::Term, std::string> getExpressionNames(bool areAssertions) const;
65
  /** get model declare sorts */
66
  std::vector<api::Sort> getModelDeclareSorts() const;
67
  /** get model declare terms */
68
  std::vector<api::Term> getModelDeclareTerms() const;
69
  /** get functions to synthesize */
70
  std::vector<api::Term> getFunctionsToSynthesize() const;
71
  /** Add declared sort to the list of model declarations. */
72
  void addModelDeclarationSort(api::Sort s);
73
  /** Add declared term to the list of model declarations. */
74
  void addModelDeclarationTerm(api::Term t);
75
  /** Add function to the list of functions to synthesize. */
76
  void addFunctionToSynthesize(api::Term t);
77
  /** reset */
78
  void reset();
79
  /** reset assertions */
80
  void resetAssertions();
81
  /** Push a scope in the expression names. */
82
  void pushScope(bool isUserContext);
83
  /** Pop a scope in the expression names. */
84
  void popScope();
85
  /** Have we pushed a scope (e.g. let or quantifier) in the current context? */
86
  bool hasPushedScope() const;
87
88
 private:
89
  /** The context manager for the scope maps. */
90
  Context d_context;
91
  /** Map terms to names */
92
  TermStringMap d_names;
93
  /** The set of terms with assertion names */
94
  TermSet d_namedAsserts;
95
  /** Declared sorts (for model printing) */
96
  SortList d_declareSorts;
97
  /** Declared terms (for model printing) */
98
  TermList d_declareTerms;
99
  /** Functions to synthesize (for response to check-synth) */
100
  TermList d_funToSynth;
101
  /**
102
   * Have we pushed a scope (e.g. a let or quantifier) in the current context?
103
   */
104
  CDO<bool> d_hasPushedScope;
105
};
106
107
10592
NamingResult SymbolManager::Implementation::setExpressionName(
108
    api::Term t, const std::string& name, bool isAssertion)
109
{
110
21184
  Trace("sym-manager") << "SymbolManager: set expression name: " << t << " -> "
111
10592
                       << name << ", isAssertion=" << isAssertion << std::endl;
112
10592
  if (d_hasPushedScope.get())
113
  {
114
    // cannot name subexpressions under binders
115
1
    return NamingResult::ERROR_IN_BINDER;
116
  }
117
118
10591
  if (isAssertion)
119
  {
120
5943
    d_namedAsserts.insert(t);
121
  }
122
10591
  if (d_names.find(t) != d_names.end())
123
  {
124
    // already named assertion
125
4716
    return NamingResult::ERROR_ALREADY_NAMED;
126
  }
127
5875
  d_names[t] = name;
128
5875
  return NamingResult::SUCCESS;
129
}
130
131
21
bool SymbolManager::Implementation::getExpressionName(api::Term t,
132
                                                      std::string& name,
133
                                                      bool isAssertion) const
134
{
135
21
  TermStringMap::const_iterator it = d_names.find(t);
136
21
  if (it == d_names.end())
137
  {
138
4
    return false;
139
  }
140
17
  if (isAssertion)
141
  {
142
    // must be an assertion name
143
17
    if (d_namedAsserts.find(t) == d_namedAsserts.end())
144
    {
145
      return false;
146
    }
147
  }
148
17
  name = (*it).second;
149
17
  return true;
150
}
151
152
7
void SymbolManager::Implementation::getExpressionNames(
153
    const std::vector<api::Term>& ts,
154
    std::vector<std::string>& names,
155
    bool areAssertions) const
156
{
157
28
  for (const api::Term& t : ts)
158
  {
159
42
    std::string name;
160
21
    if (getExpressionName(t, name, areAssertions))
161
    {
162
17
      names.push_back(name);
163
    }
164
  }
165
7
}
166
167
std::map<api::Term, std::string>
168
10
SymbolManager::Implementation::getExpressionNames(bool areAssertions) const
169
{
170
10
  std::map<api::Term, std::string> emap;
171
22
  for (TermStringMap::const_iterator it = d_names.begin(),
172
10
                                     itend = d_names.end();
173
22
       it != itend;
174
       ++it)
175
  {
176
24
    api::Term t = (*it).first;
177
12
    if (areAssertions && d_namedAsserts.find(t) == d_namedAsserts.end())
178
    {
179
      continue;
180
    }
181
12
    emap[t] = (*it).second;
182
  }
183
10
  return emap;
184
}
185
186
25
std::vector<api::Sort> SymbolManager::Implementation::getModelDeclareSorts()
187
    const
188
{
189
  std::vector<api::Sort> declareSorts(d_declareSorts.begin(),
190
25
                                      d_declareSorts.end());
191
25
  return declareSorts;
192
}
193
194
25
std::vector<api::Term> SymbolManager::Implementation::getModelDeclareTerms()
195
    const
196
{
197
  std::vector<api::Term> declareTerms(d_declareTerms.begin(),
198
25
                                      d_declareTerms.end());
199
25
  return declareTerms;
200
}
201
202
3
std::vector<api::Term> SymbolManager::Implementation::getFunctionsToSynthesize()
203
    const
204
{
205
3
  return std::vector<api::Term>(d_funToSynth.begin(), d_funToSynth.end());
206
}
207
208
3992
void SymbolManager::Implementation::addModelDeclarationSort(api::Sort s)
209
{
210
7984
  Trace("sym-manager") << "SymbolManager: addModelDeclarationSort " << s
211
3992
                       << std::endl;
212
3992
  d_declareSorts.push_back(s);
213
3992
}
214
215
175547
void SymbolManager::Implementation::addModelDeclarationTerm(api::Term t)
216
{
217
351094
  Trace("sym-manager") << "SymbolManager: addModelDeclarationTerm " << t
218
175547
                       << std::endl;
219
175547
  d_declareTerms.push_back(t);
220
175547
}
221
222
282
void SymbolManager::Implementation::addFunctionToSynthesize(api::Term f)
223
{
224
564
  Trace("sym-manager") << "SymbolManager: addFunctionToSynthesize " << f
225
282
                       << std::endl;
226
282
  d_funToSynth.push_back(f);
227
282
}
228
229
106273
void SymbolManager::Implementation::pushScope(bool isUserContext)
230
{
231
212546
  Trace("sym-manager") << "SymbolManager: pushScope, isUserContext = "
232
106273
                       << isUserContext << std::endl;
233
106273
  PrettyCheckArgument(!d_hasPushedScope.get() || !isUserContext,
234
                      "cannot push a user context within a scope context");
235
106273
  d_context.push();
236
106273
  if (!isUserContext)
237
  {
238
103184
    d_hasPushedScope = true;
239
  }
240
106273
}
241
242
105729
void SymbolManager::Implementation::popScope()
243
{
244
105729
  Trace("sym-manager") << "SymbolManager: popScope" << std::endl;
245
105729
  if (d_context.getLevel() == 0)
246
  {
247
    throw ScopeException();
248
  }
249
105729
  d_context.pop();
250
211458
  Trace("sym-manager-debug")
251
105729
      << "d_hasPushedScope is now " << d_hasPushedScope.get() << std::endl;
252
105729
}
253
254
24
bool SymbolManager::Implementation::hasPushedScope() const
255
{
256
24
  return d_hasPushedScope.get();
257
}
258
259
49
void SymbolManager::Implementation::reset()
260
{
261
49
  Trace("sym-manager") << "SymbolManager: reset" << std::endl;
262
  // clear names by popping to context level 0
263
147
  while (d_context.getLevel() > 0)
264
  {
265
49
    d_context.pop();
266
  }
267
  // push the outermost context
268
49
  d_context.push();
269
49
}
270
271
32
void SymbolManager::Implementation::resetAssertions()
272
{
273
32
  Trace("sym-manager") << "SymbolManager: resetAssertions" << std::endl;
274
  // clear names by popping to context level 1
275
44
  while (d_context.getLevel() > 1)
276
  {
277
6
    d_context.pop();
278
  }
279
32
}
280
281
// ---------------------------------------------- SymbolManager
282
283
6145
SymbolManager::SymbolManager(api::Solver* s)
284
    : d_solver(s),
285
6145
      d_implementation(new SymbolManager::Implementation()),
286
12290
      d_globalDeclarations(false)
287
{
288
6145
}
289
290
6145
SymbolManager::~SymbolManager() {}
291
292
6145
SymbolTable* SymbolManager::getSymbolTable() { return &d_symtabAllocated; }
293
294
10592
NamingResult SymbolManager::setExpressionName(api::Term t,
295
                                              const std::string& name,
296
                                              bool isAssertion)
297
{
298
10592
  return d_implementation->setExpressionName(t, name, isAssertion);
299
}
300
301
bool SymbolManager::getExpressionName(api::Term t,
302
                                      std::string& name,
303
                                      bool isAssertion) const
304
{
305
  return d_implementation->getExpressionName(t, name, isAssertion);
306
}
307
308
7
void SymbolManager::getExpressionNames(const std::vector<api::Term>& ts,
309
                                       std::vector<std::string>& names,
310
                                       bool areAssertions) const
311
{
312
7
  return d_implementation->getExpressionNames(ts, names, areAssertions);
313
}
314
315
10
std::map<api::Term, std::string> SymbolManager::getExpressionNames(
316
    bool areAssertions) const
317
{
318
10
  return d_implementation->getExpressionNames(areAssertions);
319
}
320
25
std::vector<api::Sort> SymbolManager::getModelDeclareSorts() const
321
{
322
25
  return d_implementation->getModelDeclareSorts();
323
}
324
25
std::vector<api::Term> SymbolManager::getModelDeclareTerms() const
325
{
326
25
  return d_implementation->getModelDeclareTerms();
327
}
328
329
3
std::vector<api::Term> SymbolManager::getFunctionsToSynthesize() const
330
{
331
3
  return d_implementation->getFunctionsToSynthesize();
332
}
333
334
3992
void SymbolManager::addModelDeclarationSort(api::Sort s)
335
{
336
3992
  d_implementation->addModelDeclarationSort(s);
337
3992
}
338
339
175547
void SymbolManager::addModelDeclarationTerm(api::Term t)
340
{
341
175547
  d_implementation->addModelDeclarationTerm(t);
342
175547
}
343
344
282
void SymbolManager::addFunctionToSynthesize(api::Term f)
345
{
346
282
  d_implementation->addFunctionToSynthesize(f);
347
282
}
348
349
2736
size_t SymbolManager::scopeLevel() const
350
{
351
2736
  return d_symtabAllocated.getLevel();
352
}
353
354
106280
void SymbolManager::pushScope(bool isUserContext)
355
{
356
  // we do not push user contexts when global declarations is true. This
357
  // policy applies both to the symbol table and to the symbol manager.
358
106280
  if (d_globalDeclarations && isUserContext)
359
  {
360
7
    return;
361
  }
362
106273
  d_implementation->pushScope(isUserContext);
363
106273
  d_symtabAllocated.pushScope();
364
}
365
366
105734
void SymbolManager::popScope()
367
{
368
  // If global declarations is true, then if d_hasPushedScope is false, then
369
  // the pop corresponds to a user context, which we did not push. Note this
370
  // additionally relies on the fact that user contexts cannot be pushed
371
  // within scope contexts. Hence, since we did not push the context, we
372
  // do not pop a context here.
373
105734
  if (d_globalDeclarations && !d_implementation->hasPushedScope())
374
  {
375
5
    return;
376
  }
377
105729
  d_symtabAllocated.popScope();
378
105729
  d_implementation->popScope();
379
}
380
381
17
void SymbolManager::setGlobalDeclarations(bool flag)
382
{
383
17
  d_globalDeclarations = flag;
384
17
}
385
386
185853
bool SymbolManager::getGlobalDeclarations() const
387
{
388
185853
  return d_globalDeclarations;
389
}
390
391
49
void SymbolManager::reset()
392
{
393
49
  d_symtabAllocated.reset();
394
49
  d_implementation->reset();
395
49
}
396
397
32
void SymbolManager::resetAssertions()
398
{
399
32
  d_implementation->resetAssertions();
400
32
  d_symtabAllocated.resetAssertions();
401
32
}
402
403
28194
}  // namespace cvc5