1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Andrew Reynolds, Tim King, Morgan Deters |
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 |
|
* Convenience class for scoping variable and type declarations |
14 |
|
* (implementation). |
15 |
|
*/ |
16 |
|
|
17 |
|
#include "expr/symbol_table.h" |
18 |
|
|
19 |
|
#include <ostream> |
20 |
|
#include <string> |
21 |
|
#include <unordered_map> |
22 |
|
#include <utility> |
23 |
|
|
24 |
|
#include "api/cpp/cvc5.h" |
25 |
|
#include "context/cdhashmap.h" |
26 |
|
#include "context/cdhashset.h" |
27 |
|
#include "context/context.h" |
28 |
|
|
29 |
|
namespace cvc5 { |
30 |
|
|
31 |
|
using ::cvc5::context::CDHashMap; |
32 |
|
using ::cvc5::context::CDHashSet; |
33 |
|
using ::cvc5::context::Context; |
34 |
|
using ::std::copy; |
35 |
|
using ::std::endl; |
36 |
|
using ::std::ostream_iterator; |
37 |
|
using ::std::pair; |
38 |
|
using ::std::string; |
39 |
|
using ::std::vector; |
40 |
|
|
41 |
|
/** Overloaded type trie. |
42 |
|
* |
43 |
|
* This data structure stores a trie of expressions with |
44 |
|
* the same name, and must be distinguished by their argument types. |
45 |
|
* It is context-dependent. |
46 |
|
* |
47 |
|
* Using the argument allowFunVariants, |
48 |
|
* it may either be configured to allow function variants or not, |
49 |
|
* where a function variant is function that expects the same |
50 |
|
* argument types as another. |
51 |
|
* |
52 |
|
* For example, the following definitions introduce function |
53 |
|
* variants for the symbol f: |
54 |
|
* |
55 |
|
* 1. (declare-fun f (Int) Int) and |
56 |
|
* (declare-fun f (Int) Bool) |
57 |
|
* |
58 |
|
* 2. (declare-fun f (Int) Int) and |
59 |
|
* (declare-fun f (Int) Int) |
60 |
|
* |
61 |
|
* 3. (declare-datatypes ((Tup 0)) ((f (data Int)))) and |
62 |
|
* (declare-fun f (Int) Tup) |
63 |
|
* |
64 |
|
* 4. (declare-datatypes ((Tup 0)) ((mkTup (f Int)))) and |
65 |
|
* (declare-fun f (Tup) Bool) |
66 |
|
* |
67 |
|
* If function variants is set to true, we allow function variants |
68 |
|
* but not function redefinition. In examples 2 and 3, f is |
69 |
|
* declared twice as a symbol of identical argument and range |
70 |
|
* types. We never accept these definitions. However, we do |
71 |
|
* allow examples 1 and 4 above when allowFunVariants is true. |
72 |
|
* |
73 |
|
* For 0-argument functions (constants), we always allow |
74 |
|
* function variants. That is, we always accept these examples: |
75 |
|
* |
76 |
|
* 5. (declare-fun c () Int) |
77 |
|
* (declare-fun c () Bool) |
78 |
|
* |
79 |
|
* 6. (declare-datatypes ((Enum 0)) ((c))) |
80 |
|
* (declare-fun c () Int) |
81 |
|
* |
82 |
|
* and always reject constant redefinition such as: |
83 |
|
* |
84 |
|
* 7. (declare-fun c () Int) |
85 |
|
* (declare-fun c () Int) |
86 |
|
* |
87 |
|
* 8. (declare-datatypes ((Enum 0)) ((c))) and |
88 |
|
* (declare-fun c () Enum) |
89 |
|
*/ |
90 |
|
class OverloadedTypeTrie { |
91 |
|
public: |
92 |
6056 |
OverloadedTypeTrie(Context* c, bool allowFunVariants = false) |
93 |
6056 |
: d_overloaded_symbols( |
94 |
6056 |
new (true) CDHashSet<api::Term, std::hash<api::Term>>(c)), |
95 |
12112 |
d_allowFunctionVariants(allowFunVariants) |
96 |
|
{ |
97 |
6056 |
} |
98 |
6056 |
~OverloadedTypeTrie() { d_overloaded_symbols->deleteSelf(); } |
99 |
|
|
100 |
|
/** is this function overloaded? */ |
101 |
|
bool isOverloadedFunction(api::Term fun) const; |
102 |
|
|
103 |
|
/** Get overloaded constant for type. |
104 |
|
* If possible, it returns a defined symbol with name |
105 |
|
* that has type t. Otherwise returns null expression. |
106 |
|
*/ |
107 |
|
api::Term getOverloadedConstantForType(const std::string& name, |
108 |
|
api::Sort t) const; |
109 |
|
|
110 |
|
/** |
111 |
|
* If possible, returns a defined function for a name |
112 |
|
* and a vector of expected argument types. Otherwise returns |
113 |
|
* null expression. |
114 |
|
*/ |
115 |
|
api::Term getOverloadedFunctionForTypes( |
116 |
|
const std::string& name, const std::vector<api::Sort>& argTypes) const; |
117 |
|
/** called when obj is bound to name, and prev_bound_obj was already bound to |
118 |
|
* name Returns false if the binding is invalid. |
119 |
|
*/ |
120 |
|
bool bind(const string& name, api::Term prev_bound_obj, api::Term obj); |
121 |
|
|
122 |
|
private: |
123 |
|
/** Marks expression obj with name as overloaded. |
124 |
|
* Adds relevant information to the type arg trie data structure. |
125 |
|
* It returns false if there is already an expression bound to that name |
126 |
|
* whose type expects the same arguments as the type of obj but is not |
127 |
|
* identical to the type of obj. For example, if we declare : |
128 |
|
* |
129 |
|
* (declare-datatypes () ((List (cons (hd Int) (tl List)) (nil)))) |
130 |
|
* (declare-fun cons (Int List) List) |
131 |
|
* |
132 |
|
* cons : constructor_type( Int, List, List ) |
133 |
|
* cons : function_type( Int, List, List ) |
134 |
|
* |
135 |
|
* These are put in the same place in the trie but do not have identical type, |
136 |
|
* hence we return false. |
137 |
|
*/ |
138 |
|
bool markOverloaded(const string& name, api::Term obj); |
139 |
|
/** the null expression */ |
140 |
|
api::Term d_nullTerm; |
141 |
|
// The (context-independent) trie storing that maps expected argument |
142 |
|
// vectors to symbols. All expressions stored in d_symbols are only |
143 |
|
// interpreted as active if they also appear in the context-dependent |
144 |
|
// set d_overloaded_symbols. |
145 |
88 |
class TypeArgTrie { |
146 |
|
public: |
147 |
|
// children of this node |
148 |
|
std::map<api::Sort, TypeArgTrie> d_children; |
149 |
|
// symbols at this node |
150 |
|
std::map<api::Sort, api::Term> d_symbols; |
151 |
|
}; |
152 |
|
/** for each string with operator overloading, this stores the data structure |
153 |
|
* above. */ |
154 |
|
std::unordered_map<std::string, TypeArgTrie> d_overload_type_arg_trie; |
155 |
|
/** The set of overloaded symbols. */ |
156 |
|
CDHashSet<api::Term, std::hash<api::Term>>* d_overloaded_symbols; |
157 |
|
/** allow function variants |
158 |
|
* This is true if we allow overloading (non-constant) functions that expect |
159 |
|
* the same argument types. |
160 |
|
*/ |
161 |
|
bool d_allowFunctionVariants; |
162 |
|
/** get unique overloaded function |
163 |
|
* If tat->d_symbols contains an active overloaded function, it |
164 |
|
* returns that function, where that function must be unique |
165 |
|
* if reqUnique=true. |
166 |
|
* Otherwise, it returns the null expression. |
167 |
|
*/ |
168 |
|
api::Term getOverloadedFunctionAt(const TypeArgTrie* tat, |
169 |
|
bool reqUnique = true) const; |
170 |
|
}; |
171 |
|
|
172 |
3872145 |
bool OverloadedTypeTrie::isOverloadedFunction(api::Term fun) const |
173 |
|
{ |
174 |
3872145 |
return d_overloaded_symbols->find(fun) != d_overloaded_symbols->end(); |
175 |
|
} |
176 |
|
|
177 |
6 |
api::Term OverloadedTypeTrie::getOverloadedConstantForType( |
178 |
|
const std::string& name, api::Sort t) const |
179 |
|
{ |
180 |
|
std::unordered_map<std::string, TypeArgTrie>::const_iterator it = |
181 |
6 |
d_overload_type_arg_trie.find(name); |
182 |
6 |
if (it != d_overload_type_arg_trie.end()) { |
183 |
|
std::map<api::Sort, api::Term>::const_iterator its = |
184 |
6 |
it->second.d_symbols.find(t); |
185 |
6 |
if (its != it->second.d_symbols.end()) { |
186 |
6 |
api::Term expr = its->second; |
187 |
|
// must be an active symbol |
188 |
6 |
if (isOverloadedFunction(expr)) { |
189 |
6 |
return expr; |
190 |
|
} |
191 |
|
} |
192 |
|
} |
193 |
|
return d_nullTerm; |
194 |
|
} |
195 |
|
|
196 |
14 |
api::Term OverloadedTypeTrie::getOverloadedFunctionForTypes( |
197 |
|
const std::string& name, const std::vector<api::Sort>& argTypes) const |
198 |
|
{ |
199 |
|
std::unordered_map<std::string, TypeArgTrie>::const_iterator it = |
200 |
14 |
d_overload_type_arg_trie.find(name); |
201 |
14 |
if (it != d_overload_type_arg_trie.end()) { |
202 |
14 |
const TypeArgTrie* tat = &it->second; |
203 |
30 |
for (unsigned i = 0; i < argTypes.size(); i++) { |
204 |
|
std::map<api::Sort, TypeArgTrie>::const_iterator itc = |
205 |
16 |
tat->d_children.find(argTypes[i]); |
206 |
16 |
if (itc != tat->d_children.end()) { |
207 |
16 |
tat = &itc->second; |
208 |
|
} else { |
209 |
|
Trace("parser-overloading") |
210 |
|
<< "Could not find overloaded function " << name << std::endl; |
211 |
|
|
212 |
|
// no functions match |
213 |
|
return d_nullTerm; |
214 |
|
} |
215 |
|
} |
216 |
|
// we ensure that there is *only* one active symbol at this node |
217 |
14 |
return getOverloadedFunctionAt(tat); |
218 |
|
} |
219 |
|
return d_nullTerm; |
220 |
|
} |
221 |
|
|
222 |
20 |
bool OverloadedTypeTrie::bind(const string& name, |
223 |
|
api::Term prev_bound_obj, |
224 |
|
api::Term obj) |
225 |
|
{ |
226 |
20 |
bool retprev = true; |
227 |
20 |
if (!isOverloadedFunction(prev_bound_obj)) { |
228 |
|
// mark previous as overloaded |
229 |
16 |
retprev = markOverloaded(name, prev_bound_obj); |
230 |
|
} |
231 |
|
// mark this as overloaded |
232 |
20 |
bool retobj = markOverloaded(name, obj); |
233 |
20 |
return retprev && retobj; |
234 |
|
} |
235 |
|
|
236 |
36 |
bool OverloadedTypeTrie::markOverloaded(const string& name, api::Term obj) |
237 |
|
{ |
238 |
36 |
Trace("parser-overloading") << "Overloaded function : " << name; |
239 |
36 |
Trace("parser-overloading") << " with type " << obj.getSort() << std::endl; |
240 |
|
// get the argument types |
241 |
72 |
api::Sort t = obj.getSort(); |
242 |
72 |
api::Sort rangeType = t; |
243 |
72 |
std::vector<api::Sort> argTypes; |
244 |
36 |
if (t.isFunction()) |
245 |
|
{ |
246 |
6 |
argTypes = t.getFunctionDomainSorts(); |
247 |
6 |
rangeType = t.getFunctionCodomainSort(); |
248 |
|
} |
249 |
30 |
else if (t.isConstructor()) |
250 |
|
{ |
251 |
14 |
argTypes = t.getConstructorDomainSorts(); |
252 |
14 |
rangeType = t.getConstructorCodomainSort(); |
253 |
|
} |
254 |
16 |
else if (t.isTester()) |
255 |
|
{ |
256 |
12 |
argTypes.push_back(t.getTesterDomainSort()); |
257 |
12 |
rangeType = t.getTesterCodomainSort(); |
258 |
|
} |
259 |
4 |
else if (t.isSelector()) |
260 |
|
{ |
261 |
4 |
argTypes.push_back(t.getSelectorDomainSort()); |
262 |
4 |
rangeType = t.getSelectorCodomainSort(); |
263 |
|
} |
264 |
|
// add to the trie |
265 |
36 |
TypeArgTrie* tat = &d_overload_type_arg_trie[name]; |
266 |
66 |
for (unsigned i = 0; i < argTypes.size(); i++) { |
267 |
30 |
tat = &(tat->d_children[argTypes[i]]); |
268 |
|
} |
269 |
|
|
270 |
|
// check if function variants are allowed here |
271 |
36 |
if (d_allowFunctionVariants || argTypes.empty()) |
272 |
|
{ |
273 |
|
// they are allowed, check for redefinition |
274 |
|
std::map<api::Sort, api::Term>::iterator it = |
275 |
8 |
tat->d_symbols.find(rangeType); |
276 |
8 |
if (it != tat->d_symbols.end()) |
277 |
|
{ |
278 |
|
api::Term prev_obj = it->second; |
279 |
|
// if there is already an active function with the same name and expects |
280 |
|
// the same argument types and has the same return type, we reject the |
281 |
|
// re-declaration here. |
282 |
|
if (isOverloadedFunction(prev_obj)) |
283 |
|
{ |
284 |
|
return false; |
285 |
|
} |
286 |
|
} |
287 |
|
} |
288 |
|
else |
289 |
|
{ |
290 |
|
// they are not allowed, we cannot have any function defined here. |
291 |
56 |
api::Term existingFun = getOverloadedFunctionAt(tat, false); |
292 |
28 |
if (!existingFun.isNull()) |
293 |
|
{ |
294 |
|
return false; |
295 |
|
} |
296 |
|
} |
297 |
|
|
298 |
|
// otherwise, update the symbols |
299 |
36 |
d_overloaded_symbols->insert(obj); |
300 |
36 |
tat->d_symbols[rangeType] = obj; |
301 |
36 |
return true; |
302 |
|
} |
303 |
|
|
304 |
42 |
api::Term OverloadedTypeTrie::getOverloadedFunctionAt( |
305 |
|
const OverloadedTypeTrie::TypeArgTrie* tat, bool reqUnique) const |
306 |
|
{ |
307 |
84 |
api::Term retExpr; |
308 |
14 |
for (std::map<api::Sort, api::Term>::const_iterator its = |
309 |
42 |
tat->d_symbols.begin(); |
310 |
56 |
its != tat->d_symbols.end(); |
311 |
|
++its) |
312 |
|
{ |
313 |
28 |
api::Term expr = its->second; |
314 |
14 |
if (isOverloadedFunction(expr)) |
315 |
|
{ |
316 |
14 |
if (retExpr.isNull()) |
317 |
|
{ |
318 |
14 |
if (!reqUnique) |
319 |
|
{ |
320 |
|
return expr; |
321 |
|
} |
322 |
|
else |
323 |
|
{ |
324 |
14 |
retExpr = expr; |
325 |
|
} |
326 |
|
} |
327 |
|
else |
328 |
|
{ |
329 |
|
// multiple functions match |
330 |
|
return d_nullTerm; |
331 |
|
} |
332 |
|
} |
333 |
|
} |
334 |
42 |
return retExpr; |
335 |
|
} |
336 |
|
|
337 |
|
class SymbolTable::Implementation { |
338 |
|
public: |
339 |
6056 |
Implementation() |
340 |
6056 |
: d_context(), |
341 |
|
d_exprMap(&d_context), |
342 |
|
d_typeMap(&d_context), |
343 |
6056 |
d_overload_trie(&d_context) |
344 |
|
{ |
345 |
|
// use an outermost push, to be able to clear definitions not at level zero |
346 |
6056 |
d_context.push(); |
347 |
6056 |
} |
348 |
|
|
349 |
6056 |
~Implementation() { d_context.pop(); } |
350 |
|
|
351 |
|
bool bind(const string& name, api::Term obj, bool levelZero, bool doOverload); |
352 |
|
void bindType(const string& name, api::Sort t, bool levelZero = false); |
353 |
|
void bindType(const string& name, |
354 |
|
const vector<api::Sort>& params, |
355 |
|
api::Sort t, |
356 |
|
bool levelZero = false); |
357 |
|
bool isBound(const string& name) const; |
358 |
|
bool isBoundType(const string& name) const; |
359 |
|
api::Term lookup(const string& name) const; |
360 |
|
api::Sort lookupType(const string& name) const; |
361 |
|
api::Sort lookupType(const string& name, |
362 |
|
const vector<api::Sort>& params) const; |
363 |
|
size_t lookupArity(const string& name); |
364 |
|
void popScope(); |
365 |
|
void pushScope(); |
366 |
|
size_t getLevel() const; |
367 |
|
void reset(); |
368 |
|
void resetAssertions(); |
369 |
|
//------------------------ operator overloading |
370 |
|
/** implementation of function from header */ |
371 |
|
bool isOverloadedFunction(api::Term fun) const; |
372 |
|
|
373 |
|
/** implementation of function from header */ |
374 |
|
api::Term getOverloadedConstantForType(const std::string& name, |
375 |
|
api::Sort t) const; |
376 |
|
|
377 |
|
/** implementation of function from header */ |
378 |
|
api::Term getOverloadedFunctionForTypes( |
379 |
|
const std::string& name, const std::vector<api::Sort>& argTypes) const; |
380 |
|
//------------------------ end operator overloading |
381 |
|
private: |
382 |
|
/** The context manager for the scope maps. */ |
383 |
|
Context d_context; |
384 |
|
|
385 |
|
/** A map for expressions. */ |
386 |
|
CDHashMap<string, api::Term> d_exprMap; |
387 |
|
|
388 |
|
/** A map for types. */ |
389 |
|
using TypeMap = CDHashMap<string, std::pair<vector<api::Sort>, api::Sort>>; |
390 |
|
TypeMap d_typeMap; |
391 |
|
|
392 |
|
//------------------------ operator overloading |
393 |
|
// the null expression |
394 |
|
api::Term d_nullTerm; |
395 |
|
// overloaded type trie, stores all information regarding overloading |
396 |
|
OverloadedTypeTrie d_overload_trie; |
397 |
|
/** bind with overloading |
398 |
|
* This is called whenever obj is bound to name where overloading symbols is |
399 |
|
* allowed. If a symbol is previously bound to that name, it marks both as |
400 |
|
* overloaded. Returns false if the binding was invalid. |
401 |
|
*/ |
402 |
|
bool bindWithOverloading(const string& name, api::Term obj); |
403 |
|
//------------------------ end operator overloading |
404 |
|
}; /* SymbolTable::Implementation */ |
405 |
|
|
406 |
371157 |
bool SymbolTable::Implementation::bind(const string& name, |
407 |
|
api::Term obj, |
408 |
|
bool levelZero, |
409 |
|
bool doOverload) |
410 |
|
{ |
411 |
371157 |
PrettyCheckArgument(!obj.isNull(), obj, "cannot bind to a null api::Term"); |
412 |
742314 |
Trace("sym-table") << "SymbolTable: bind " << name |
413 |
371157 |
<< ", levelZero=" << levelZero |
414 |
371157 |
<< ", doOverload=" << doOverload << std::endl; |
415 |
371157 |
if (doOverload) { |
416 |
184404 |
if (!bindWithOverloading(name, obj)) { |
417 |
|
return false; |
418 |
|
} |
419 |
|
} |
420 |
371157 |
if (levelZero) { |
421 |
10198 |
d_exprMap.insertAtContextLevelZero(name, obj); |
422 |
|
} else { |
423 |
360959 |
d_exprMap.insert(name, obj); |
424 |
|
} |
425 |
371157 |
return true; |
426 |
|
} |
427 |
|
|
428 |
19355527 |
bool SymbolTable::Implementation::isBound(const string& name) const { |
429 |
19355527 |
return d_exprMap.find(name) != d_exprMap.end(); |
430 |
|
} |
431 |
|
|
432 |
3872105 |
api::Term SymbolTable::Implementation::lookup(const string& name) const |
433 |
|
{ |
434 |
3872105 |
Assert(isBound(name)); |
435 |
7744210 |
api::Term expr = (*d_exprMap.find(name)).second; |
436 |
3872105 |
if (isOverloadedFunction(expr)) { |
437 |
20 |
return d_nullTerm; |
438 |
|
} else { |
439 |
3872085 |
return expr; |
440 |
|
} |
441 |
|
} |
442 |
|
|
443 |
29270 |
void SymbolTable::Implementation::bindType(const string& name, |
444 |
|
api::Sort t, |
445 |
|
bool levelZero) |
446 |
|
{ |
447 |
29270 |
if (levelZero) { |
448 |
22209 |
d_typeMap.insertAtContextLevelZero(name, make_pair(vector<api::Sort>(), t)); |
449 |
|
} else { |
450 |
7061 |
d_typeMap.insert(name, make_pair(vector<api::Sort>(), t)); |
451 |
|
} |
452 |
29270 |
} |
453 |
|
|
454 |
325 |
void SymbolTable::Implementation::bindType(const string& name, |
455 |
|
const vector<api::Sort>& params, |
456 |
|
api::Sort t, |
457 |
|
bool levelZero) |
458 |
|
{ |
459 |
325 |
if (Debug.isOn("sort")) { |
460 |
|
Debug("sort") << "bindType(" << name << ", ["; |
461 |
|
if (params.size() > 0) { |
462 |
|
copy(params.begin(), |
463 |
|
params.end() - 1, |
464 |
|
ostream_iterator<api::Sort>(Debug("sort"), ", ")); |
465 |
|
Debug("sort") << params.back(); |
466 |
|
} |
467 |
|
Debug("sort") << "], " << t << ")" << endl; |
468 |
|
} |
469 |
325 |
if (levelZero) { |
470 |
4 |
d_typeMap.insertAtContextLevelZero(name, make_pair(params, t)); |
471 |
|
} else { |
472 |
321 |
d_typeMap.insert(name, make_pair(params, t)); |
473 |
|
} |
474 |
325 |
} |
475 |
|
|
476 |
635907 |
bool SymbolTable::Implementation::isBoundType(const string& name) const { |
477 |
635907 |
return d_typeMap.find(name) != d_typeMap.end(); |
478 |
|
} |
479 |
|
|
480 |
277453 |
api::Sort SymbolTable::Implementation::lookupType(const string& name) const |
481 |
|
{ |
482 |
|
std::pair<std::vector<api::Sort>, api::Sort> p = |
483 |
554906 |
(*d_typeMap.find(name)).second; |
484 |
277453 |
PrettyCheckArgument(p.first.size() == 0, name, |
485 |
|
"type constructor arity is wrong: " |
486 |
|
"`%s' requires %u parameters but was provided 0", |
487 |
|
name.c_str(), p.first.size()); |
488 |
554906 |
return p.second; |
489 |
|
} |
490 |
|
|
491 |
590 |
api::Sort SymbolTable::Implementation::lookupType( |
492 |
|
const string& name, const vector<api::Sort>& params) const |
493 |
|
{ |
494 |
|
std::pair<std::vector<api::Sort>, api::Sort> p = |
495 |
1180 |
(*d_typeMap.find(name)).second; |
496 |
590 |
PrettyCheckArgument(p.first.size() == params.size(), params, |
497 |
|
"type constructor arity is wrong: " |
498 |
|
"`%s' requires %u parameters but was provided %u", |
499 |
|
name.c_str(), p.first.size(), params.size()); |
500 |
590 |
if (p.first.size() == 0) { |
501 |
|
PrettyCheckArgument(p.second.isUninterpretedSort(), name.c_str()); |
502 |
|
return p.second; |
503 |
|
} |
504 |
590 |
if (p.second.isDatatype()) |
505 |
|
{ |
506 |
173 |
PrettyCheckArgument( |
507 |
|
p.second.isParametricDatatype(), name, "expected parametric datatype"); |
508 |
173 |
return p.second.instantiate(params); |
509 |
|
} |
510 |
417 |
bool isSortConstructor = p.second.isSortConstructor(); |
511 |
417 |
if (Debug.isOn("sort")) |
512 |
|
{ |
513 |
|
Debug("sort") << "instantiating using a sort " |
514 |
|
<< (isSortConstructor ? "constructor" : "substitution") |
515 |
|
<< std::endl; |
516 |
|
Debug("sort") << "have formals ["; |
517 |
|
copy(p.first.begin(), |
518 |
|
p.first.end() - 1, |
519 |
|
ostream_iterator<api::Sort>(Debug("sort"), ", ")); |
520 |
|
Debug("sort") << p.first.back() << "]" << std::endl << "parameters ["; |
521 |
|
copy(params.begin(), |
522 |
|
params.end() - 1, |
523 |
|
ostream_iterator<api::Sort>(Debug("sort"), ", ")); |
524 |
|
Debug("sort") << params.back() << "]" << endl |
525 |
|
<< "type ctor " << name << std::endl |
526 |
|
<< "type is " << p.second << std::endl; |
527 |
|
} |
528 |
|
api::Sort instantiation = isSortConstructor |
529 |
|
? p.second.instantiate(params) |
530 |
834 |
: p.second.substitute(p.first, params); |
531 |
|
|
532 |
417 |
Debug("sort") << "instance is " << instantiation << std::endl; |
533 |
|
|
534 |
417 |
return instantiation; |
535 |
|
} |
536 |
|
|
537 |
6184 |
size_t SymbolTable::Implementation::lookupArity(const string& name) { |
538 |
|
std::pair<std::vector<api::Sort>, api::Sort> p = |
539 |
12368 |
(*d_typeMap.find(name)).second; |
540 |
12368 |
return p.first.size(); |
541 |
|
} |
542 |
|
|
543 |
102144 |
void SymbolTable::Implementation::popScope() { |
544 |
|
// should not pop beyond level one |
545 |
102144 |
if (d_context.getLevel() == 1) |
546 |
|
{ |
547 |
2 |
throw ScopeException(); |
548 |
|
} |
549 |
102142 |
d_context.pop(); |
550 |
102142 |
} |
551 |
|
|
552 |
102585 |
void SymbolTable::Implementation::pushScope() { d_context.push(); } |
553 |
|
|
554 |
2211 |
size_t SymbolTable::Implementation::getLevel() const { |
555 |
2211 |
return d_context.getLevel(); |
556 |
|
} |
557 |
|
|
558 |
47 |
void SymbolTable::Implementation::reset() { |
559 |
47 |
Trace("sym-table") << "SymbolTable: reset" << std::endl; |
560 |
47 |
this->SymbolTable::Implementation::~Implementation(); |
561 |
47 |
new (this) SymbolTable::Implementation(); |
562 |
47 |
} |
563 |
|
|
564 |
31 |
void SymbolTable::Implementation::resetAssertions() |
565 |
|
{ |
566 |
31 |
Trace("sym-table") << "SymbolTable: resetAssertions" << std::endl; |
567 |
|
// pop all contexts |
568 |
105 |
while (d_context.getLevel() > 0) |
569 |
|
{ |
570 |
37 |
d_context.pop(); |
571 |
|
} |
572 |
31 |
d_context.push(); |
573 |
31 |
} |
574 |
|
|
575 |
3872105 |
bool SymbolTable::Implementation::isOverloadedFunction(api::Term fun) const |
576 |
|
{ |
577 |
3872105 |
return d_overload_trie.isOverloadedFunction(fun); |
578 |
|
} |
579 |
|
|
580 |
6 |
api::Term SymbolTable::Implementation::getOverloadedConstantForType( |
581 |
|
const std::string& name, api::Sort t) const |
582 |
|
{ |
583 |
6 |
return d_overload_trie.getOverloadedConstantForType(name, t); |
584 |
|
} |
585 |
|
|
586 |
14 |
api::Term SymbolTable::Implementation::getOverloadedFunctionForTypes( |
587 |
|
const std::string& name, const std::vector<api::Sort>& argTypes) const |
588 |
|
{ |
589 |
14 |
return d_overload_trie.getOverloadedFunctionForTypes(name, argTypes); |
590 |
|
} |
591 |
|
|
592 |
184404 |
bool SymbolTable::Implementation::bindWithOverloading(const string& name, |
593 |
|
api::Term obj) |
594 |
|
{ |
595 |
184404 |
CDHashMap<string, api::Term>::const_iterator it = d_exprMap.find(name); |
596 |
184404 |
if (it != d_exprMap.end()) |
597 |
|
{ |
598 |
20 |
const api::Term& prev_bound_obj = (*it).second; |
599 |
20 |
if (prev_bound_obj != obj) { |
600 |
20 |
return d_overload_trie.bind(name, prev_bound_obj, obj); |
601 |
|
} |
602 |
|
} |
603 |
184384 |
return true; |
604 |
|
} |
605 |
|
|
606 |
|
bool SymbolTable::isOverloadedFunction(api::Term fun) const |
607 |
|
{ |
608 |
|
return d_implementation->isOverloadedFunction(fun); |
609 |
|
} |
610 |
|
|
611 |
6 |
api::Term SymbolTable::getOverloadedConstantForType(const std::string& name, |
612 |
|
api::Sort t) const |
613 |
|
{ |
614 |
6 |
return d_implementation->getOverloadedConstantForType(name, t); |
615 |
|
} |
616 |
|
|
617 |
14 |
api::Term SymbolTable::getOverloadedFunctionForTypes( |
618 |
|
const std::string& name, const std::vector<api::Sort>& argTypes) const |
619 |
|
{ |
620 |
14 |
return d_implementation->getOverloadedFunctionForTypes(name, argTypes); |
621 |
|
} |
622 |
|
|
623 |
6009 |
SymbolTable::SymbolTable() : d_implementation(new SymbolTable::Implementation()) |
624 |
|
{ |
625 |
6009 |
} |
626 |
|
|
627 |
6009 |
SymbolTable::~SymbolTable() {} |
628 |
371157 |
bool SymbolTable::bind(const string& name, |
629 |
|
api::Term obj, |
630 |
|
bool levelZero, |
631 |
|
bool doOverload) |
632 |
|
{ |
633 |
371157 |
return d_implementation->bind(name, obj, levelZero, doOverload); |
634 |
|
} |
635 |
|
|
636 |
29270 |
void SymbolTable::bindType(const string& name, api::Sort t, bool levelZero) |
637 |
|
{ |
638 |
29270 |
d_implementation->bindType(name, t, levelZero); |
639 |
29270 |
} |
640 |
|
|
641 |
325 |
void SymbolTable::bindType(const string& name, |
642 |
|
const vector<api::Sort>& params, |
643 |
|
api::Sort t, |
644 |
|
bool levelZero) |
645 |
|
{ |
646 |
325 |
d_implementation->bindType(name, params, t, levelZero); |
647 |
325 |
} |
648 |
|
|
649 |
15483422 |
bool SymbolTable::isBound(const string& name) const |
650 |
|
{ |
651 |
15483422 |
return d_implementation->isBound(name); |
652 |
|
} |
653 |
635907 |
bool SymbolTable::isBoundType(const string& name) const |
654 |
|
{ |
655 |
635907 |
return d_implementation->isBoundType(name); |
656 |
|
} |
657 |
3872105 |
api::Term SymbolTable::lookup(const string& name) const |
658 |
|
{ |
659 |
3872105 |
return d_implementation->lookup(name); |
660 |
|
} |
661 |
277453 |
api::Sort SymbolTable::lookupType(const string& name) const |
662 |
|
{ |
663 |
277453 |
return d_implementation->lookupType(name); |
664 |
|
} |
665 |
|
|
666 |
590 |
api::Sort SymbolTable::lookupType(const string& name, |
667 |
|
const vector<api::Sort>& params) const |
668 |
|
{ |
669 |
590 |
return d_implementation->lookupType(name, params); |
670 |
|
} |
671 |
6184 |
size_t SymbolTable::lookupArity(const string& name) { |
672 |
6184 |
return d_implementation->lookupArity(name); |
673 |
|
} |
674 |
102144 |
void SymbolTable::popScope() { d_implementation->popScope(); } |
675 |
102585 |
void SymbolTable::pushScope() { d_implementation->pushScope(); } |
676 |
2211 |
size_t SymbolTable::getLevel() const { return d_implementation->getLevel(); } |
677 |
47 |
void SymbolTable::reset() { d_implementation->reset(); } |
678 |
31 |
void SymbolTable::resetAssertions() { d_implementation->resetAssertions(); } |
679 |
|
|
680 |
27735 |
} // namespace cvc5 |