1 /********************* */
2 /*! \file symbol_table.cpp
4 ** Top contributors (to current version):
5 ** Morgan Deters, Christopher L. Conway, Francois Bobot
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2017 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.\endverbatim
12 ** \brief Convenience class for scoping variable and type
13 ** declarations (implementation)
15 ** Convenience class for scoping variable and type declarations
19 #include "expr/symbol_table.h"
25 #include "context/cdhashmap.h"
26 #include "context/cdhashset.h"
27 #include "context/context.h"
28 #include "expr/expr.h"
29 #include "expr/expr_manager_scope.h"
30 #include "expr/type.h"
34 using ::CVC4::context::CDHashMap
;
35 using ::CVC4::context::CDHashSet
;
36 using ::CVC4::context::Context
;
39 using ::std::ostream_iterator
;
44 class SymbolTable::Implementation
{
48 d_exprMap(new (true) CDHashMap
<string
, Expr
>(&d_context
)),
49 d_typeMap(new (true) TypeMap(&d_context
)),
50 d_functions(new (true) CDHashSet
<Expr
, ExprHashFunction
>(&d_context
)) {}
52 void bind(const string
& name
, Expr obj
, bool levelZero
) throw();
53 void bindDefinedFunction(const string
& name
, Expr obj
,
54 bool levelZero
) throw();
55 void bindType(const string
& name
, Type t
, bool levelZero
= false) throw();
56 void bindType(const string
& name
, const vector
<Type
>& params
, Type t
,
57 bool levelZero
= false) throw();
58 bool isBound(const string
& name
) const throw();
59 bool isBoundDefinedFunction(const string
& name
) const throw();
60 bool isBoundDefinedFunction(Expr func
) const throw();
61 bool isBoundType(const string
& name
) const throw();
62 Expr
lookup(const string
& name
) const throw();
63 Type
lookupType(const string
& name
) const throw();
64 Type
lookupType(const string
& name
, const vector
<Type
>& params
) const throw();
65 size_t lookupArity(const string
& name
);
66 void popScope() throw(ScopeException
);
67 void pushScope() throw();
68 size_t getLevel() const throw();
72 /** The context manager for the scope maps. */
75 /** A map for expressions. */
76 CDHashMap
<string
, Expr
>* d_exprMap
;
78 /** A map for types. */
79 using TypeMap
= CDHashMap
<string
, std::pair
<vector
<Type
>, Type
>>;
82 /** A set of defined functions. */
83 CDHashSet
<Expr
, ExprHashFunction
>* d_functions
;
84 }; /* SymbolTable::Implementation */
86 void SymbolTable::Implementation::bind(const string
& name
, Expr obj
,
87 bool levelZero
) throw() {
88 PrettyCheckArgument(!obj
.isNull(), obj
, "cannot bind to a null Expr");
89 ExprManagerScope
ems(obj
);
91 d_exprMap
->insertAtContextLevelZero(name
, obj
);
93 d_exprMap
->insert(name
, obj
);
97 void SymbolTable::Implementation::bindDefinedFunction(const string
& name
,
99 bool levelZero
) throw() {
100 PrettyCheckArgument(!obj
.isNull(), obj
, "cannot bind to a null Expr");
101 ExprManagerScope
ems(obj
);
103 d_exprMap
->insertAtContextLevelZero(name
, obj
);
104 d_functions
->insertAtContextLevelZero(obj
);
106 d_exprMap
->insert(name
, obj
);
107 d_functions
->insert(obj
);
111 bool SymbolTable::Implementation::isBound(const string
& name
) const throw() {
112 return d_exprMap
->find(name
) != d_exprMap
->end();
115 bool SymbolTable::Implementation::isBoundDefinedFunction(
116 const string
& name
) const throw() {
117 CDHashMap
<string
, Expr
>::iterator found
= d_exprMap
->find(name
);
118 return found
!= d_exprMap
->end() && d_functions
->contains((*found
).second
);
121 bool SymbolTable::Implementation::isBoundDefinedFunction(Expr func
) const
123 return d_functions
->contains(func
);
126 Expr
SymbolTable::Implementation::lookup(const string
& name
) const throw() {
127 return (*d_exprMap
->find(name
)).second
;
130 void SymbolTable::Implementation::bindType(const string
& name
, Type t
,
131 bool levelZero
) throw() {
133 d_typeMap
->insertAtContextLevelZero(name
, make_pair(vector
<Type
>(), t
));
135 d_typeMap
->insert(name
, make_pair(vector
<Type
>(), t
));
139 void SymbolTable::Implementation::bindType(const string
& name
,
140 const vector
<Type
>& params
, Type t
,
141 bool levelZero
) throw() {
142 if (Debug
.isOn("sort")) {
143 Debug("sort") << "bindType(" << name
<< ", [";
144 if (params
.size() > 0) {
145 copy(params
.begin(), params
.end() - 1,
146 ostream_iterator
<Type
>(Debug("sort"), ", "));
147 Debug("sort") << params
.back();
149 Debug("sort") << "], " << t
<< ")" << endl
;
152 d_typeMap
->insertAtContextLevelZero(name
, make_pair(params
, t
));
154 d_typeMap
->insert(name
, make_pair(params
, t
));
158 bool SymbolTable::Implementation::isBoundType(const string
& name
) const
160 return d_typeMap
->find(name
) != d_typeMap
->end();
163 Type
SymbolTable::Implementation::lookupType(const string
& name
) const throw() {
164 pair
<vector
<Type
>, Type
> p
= (*d_typeMap
->find(name
)).second
;
165 PrettyCheckArgument(p
.first
.size() == 0, name
,
166 "type constructor arity is wrong: "
167 "`%s' requires %u parameters but was provided 0",
168 name
.c_str(), p
.first
.size());
172 Type
SymbolTable::Implementation::lookupType(const string
& name
,
173 const vector
<Type
>& params
) const
175 pair
<vector
<Type
>, Type
> p
= (*d_typeMap
->find(name
)).second
;
176 PrettyCheckArgument(p
.first
.size() == params
.size(), params
,
177 "type constructor arity is wrong: "
178 "`%s' requires %u parameters but was provided %u",
179 name
.c_str(), p
.first
.size(), params
.size());
180 if (p
.first
.size() == 0) {
181 PrettyCheckArgument(p
.second
.isSort(), name
.c_str());
184 if (p
.second
.isSortConstructor()) {
185 if (Debug
.isOn("sort")) {
186 Debug("sort") << "instantiating using a sort constructor" << endl
;
187 Debug("sort") << "have formals [";
188 copy(p
.first
.begin(), p
.first
.end() - 1,
189 ostream_iterator
<Type
>(Debug("sort"), ", "));
190 Debug("sort") << p
.first
.back() << "]" << endl
<< "parameters [";
191 copy(params
.begin(), params
.end() - 1,
192 ostream_iterator
<Type
>(Debug("sort"), ", "));
193 Debug("sort") << params
.back() << "]" << endl
194 << "type ctor " << name
<< endl
195 << "type is " << p
.second
<< endl
;
198 Type instantiation
= SortConstructorType(p
.second
).instantiate(params
);
200 Debug("sort") << "instance is " << instantiation
<< endl
;
202 return instantiation
;
203 } else if (p
.second
.isDatatype()) {
204 PrettyCheckArgument(DatatypeType(p
.second
).isParametric(), name
,
205 "expected parametric datatype");
206 return DatatypeType(p
.second
).instantiate(params
);
208 if (Debug
.isOn("sort")) {
209 Debug("sort") << "instantiating using a sort substitution" << endl
;
210 Debug("sort") << "have formals [";
211 copy(p
.first
.begin(), p
.first
.end() - 1,
212 ostream_iterator
<Type
>(Debug("sort"), ", "));
213 Debug("sort") << p
.first
.back() << "]" << endl
<< "parameters [";
214 copy(params
.begin(), params
.end() - 1,
215 ostream_iterator
<Type
>(Debug("sort"), ", "));
216 Debug("sort") << params
.back() << "]" << endl
217 << "type ctor " << name
<< endl
218 << "type is " << p
.second
<< endl
;
221 Type instantiation
= p
.second
.substitute(p
.first
, params
);
223 Debug("sort") << "instance is " << instantiation
<< endl
;
225 return instantiation
;
229 size_t SymbolTable::Implementation::lookupArity(const string
& name
) {
230 pair
<vector
<Type
>, Type
> p
= (*d_typeMap
->find(name
)).second
;
231 return p
.first
.size();
234 void SymbolTable::Implementation::popScope() throw(ScopeException
) {
235 if (d_context
.getLevel() == 0) {
236 throw ScopeException();
241 void SymbolTable::Implementation::pushScope() throw() { d_context
.push(); }
243 size_t SymbolTable::Implementation::getLevel() const throw() {
244 return d_context
.getLevel();
247 void SymbolTable::Implementation::reset() {
248 this->SymbolTable::Implementation::~Implementation();
249 new (this) SymbolTable::Implementation();
252 SymbolTable::SymbolTable()
253 : d_implementation(new SymbolTable::Implementation()) {}
255 SymbolTable::~SymbolTable() {}
257 void SymbolTable::bind(const string
& name
, Expr obj
, bool levelZero
) throw() {
258 d_implementation
->bind(name
, obj
, levelZero
);
261 void SymbolTable::bindDefinedFunction(const string
& name
, Expr obj
,
262 bool levelZero
) throw() {
263 d_implementation
->bindDefinedFunction(name
, obj
, levelZero
);
266 void SymbolTable::bindType(const string
& name
, Type t
, bool levelZero
) throw() {
267 d_implementation
->bindType(name
, t
, levelZero
);
270 void SymbolTable::bindType(const string
& name
, const vector
<Type
>& params
,
271 Type t
, bool levelZero
) throw() {
272 d_implementation
->bindType(name
, params
, t
, levelZero
);
275 bool SymbolTable::isBound(const string
& name
) const throw() {
276 return d_implementation
->isBound(name
);
279 bool SymbolTable::isBoundDefinedFunction(const string
& name
) const throw() {
280 return d_implementation
->isBoundDefinedFunction(name
);
283 bool SymbolTable::isBoundDefinedFunction(Expr func
) const throw() {
284 return d_implementation
->isBoundDefinedFunction(func
);
286 bool SymbolTable::isBoundType(const string
& name
) const throw() {
287 return d_implementation
->isBoundType(name
);
289 Expr
SymbolTable::lookup(const string
& name
) const throw() {
290 return d_implementation
->lookup(name
);
292 Type
SymbolTable::lookupType(const string
& name
) const throw() {
293 return d_implementation
->lookupType(name
);
296 Type
SymbolTable::lookupType(const string
& name
,
297 const vector
<Type
>& params
) const throw() {
298 return d_implementation
->lookupType(name
, params
);
300 size_t SymbolTable::lookupArity(const string
& name
) {
301 return d_implementation
->lookupArity(name
);
303 void SymbolTable::popScope() throw(ScopeException
) {
304 d_implementation
->popScope();
307 void SymbolTable::pushScope() throw() { d_implementation
->pushScope(); }
308 size_t SymbolTable::getLevel() const throw() {
309 return d_implementation
->getLevel();
311 void SymbolTable::reset() { d_implementation
->reset(); }