This is in preparation for having the symbol manager manage expression names at the parser level instead of inside SmtEngine.
This adds some necessary features regarding scopes and global declarations.
This PR still does not change the behavior of the parser.
#include "context/cdhashmap.h"
#include "context/cdhashset.h"
+#include "context/cdo.h"
using namespace CVC4::context;
public:
Implementation()
- : d_context(), d_names(&d_context), d_namedAsserts(&d_context)
+ : d_context(),
+ d_names(&d_context),
+ d_namedAsserts(&d_context),
+ d_hasPushedScope(&d_context, false)
{
}
bool areAssertions = false) const;
/** reset */
void reset();
+ /** Push a scope in the expression names. */
+ void pushScope(bool isUserContext);
+ /** Pop a scope in the expression names. */
+ void popScope();
private:
/** The context manager for the scope maps. */
TermStringMap d_names;
/** The set of terms with assertion names */
TermSet d_namedAsserts;
+ /**
+ * Have we pushed a scope (e.g. a let or quantifier) in the current context?
+ */
+ CDO<bool> d_hasPushedScope;
};
bool SymbolManager::Implementation::setExpressionName(api::Term t,
const std::string& name,
bool isAssertion)
{
+ // cannot name subexpressions under quantifiers
+ PrettyCheckArgument(
+ !d_hasPushedScope.get(), name, "cannot name function in a scope");
if (d_names.find(t) != d_names.end())
{
// already named assertion
}
}
+void SymbolManager::Implementation::pushScope(bool isUserContext)
+{
+ d_context.push();
+ if (!isUserContext)
+ {
+ d_hasPushedScope = true;
+ }
+}
+
+void SymbolManager::Implementation::popScope()
+{
+ if (d_context.getLevel() == 0)
+ {
+ throw ScopeException();
+ }
+ d_context.pop();
+}
+
void SymbolManager::Implementation::reset()
{
// clear names?
// ---------------------------------------------- SymbolManager
SymbolManager::SymbolManager(api::Solver* s)
- : d_solver(s), d_implementation(new SymbolManager::Implementation())
+ : d_solver(s),
+ d_implementation(new SymbolManager::Implementation()),
+ d_globalDeclarations(false)
{
}
return d_symtabAllocated.getLevel();
}
-void SymbolManager::pushScope() { d_symtabAllocated.pushScope(); }
+void SymbolManager::pushScope(bool isUserContext)
+{
+ d_implementation->pushScope(isUserContext);
+ d_symtabAllocated.pushScope();
+}
void SymbolManager::popScope() { d_symtabAllocated.popScope(); }
+void SymbolManager::setGlobalDeclarations(bool flag)
+{
+ d_globalDeclarations = flag;
+}
+
+bool SymbolManager::getGlobalDeclarations() const
+{
+ return d_globalDeclarations;
+}
+
void SymbolManager::reset()
{
d_symtabAllocated.reset();
size_t scopeLevel() const;
/**
* Push a scope in the symbol table.
+ *
+ * @param isUserContext If true, this push is denoting a push of the user
+ * context, e.g. via an smt2 push/pop command. Otherwise, this push is
+ * due to a let/quantifier binding.
*/
- void pushScope();
+ void pushScope(bool isUserContext);
/**
* Pop a scope in the symbol table.
*/
* Reset this symbol manager, which resets the symbol table.
*/
void reset();
+ /** Set global declarations to the value flag. */
+ void setGlobalDeclarations(bool flag);
+ /** Get global declarations flag. */
+ bool getGlobalDeclarations() const;
private:
/** The API Solver object. */
/** The implementation of the symbol manager */
class Implementation;
std::unique_ptr<Implementation> d_implementation;
+ /**
+ * Whether the global declarations option is enabled. This corresponds to the
+ * SMT-LIB option :global-declarations. By default, its value is false.
+ */
+ bool d_globalDeclarations;
};
} // namespace CVC4
d_symman(sm),
d_symtab(sm->getSymbolTable()),
d_assertionLevel(0),
- d_globalDeclarations(false),
d_anonymousFunctionCount(0),
d_done(false),
d_checksEnabled(true),
uint32_t flags,
bool doOverload)
{
- if (d_globalDeclarations) {
+ if (d_symman->getGlobalDeclarations())
+ {
flags |= ExprManager::VAR_FLAG_GLOBAL;
}
Debug("parser") << "bindVar(" << name << ", " << type << ")" << std::endl;
const api::Sort& type,
uint32_t flags)
{
- if (d_globalDeclarations) {
+ bool globalDecls = d_symman->getGlobalDeclarations();
+ if (globalDecls)
+ {
flags |= ExprManager::VAR_FLAG_GLOBAL;
}
stringstream name;
uint32_t flags,
bool doOverload)
{
- if (d_globalDeclarations) {
+ bool globalDecls = d_symman->getGlobalDeclarations();
+ if (globalDecls)
+ {
flags |= ExprManager::VAR_FLAG_GLOBAL;
}
std::vector<api::Term> vars;
Debug("parser") << "newSort(" << name << ")" << std::endl;
api::Sort type =
api::Sort(d_solver, d_solver->getExprManager()->mkSort(name, flags));
+ bool globalDecls = d_symman->getGlobalDeclarations();
defineType(
- name,
- type,
- d_globalDeclarations && !(flags & ExprManager::SORT_FLAG_PLACEHOLDER));
+ name, type, globalDecls && !(flags & ExprManager::SORT_FLAG_PLACEHOLDER));
return type;
}
api::Sort type = api::Sort(
d_solver,
d_solver->getExprManager()->mkSortConstructor(name, arity, flags));
- defineType(
- name,
- vector<api::Sort>(arity),
- type,
- d_globalDeclarations && !(flags & ExprManager::SORT_FLAG_PLACEHOLDER));
+ bool globalDecls = d_symman->getGlobalDeclarations();
+ defineType(name,
+ vector<api::Sort>(arity),
+ type,
+ globalDecls && !(flags & ExprManager::SORT_FLAG_PLACEHOLDER));
return type;
}
d_solver->mkDatatypeSorts(datatypes, d_unresolved);
assert(datatypes.size() == types.size());
+ bool globalDecls = d_symman->getGlobalDeclarations();
for (unsigned i = 0; i < datatypes.size(); ++i) {
api::Sort t = types[i];
if (t.isParametricDatatype())
{
std::vector<api::Sort> paramTypes = t.getDatatypeParamSorts();
- defineType(name, paramTypes, t, d_globalDeclarations);
+ defineType(name, paramTypes, t, globalDecls);
}
else
{
- defineType(name, t, d_globalDeclarations);
+ defineType(name, t, globalDecls);
}
std::unordered_set< std::string > consNames;
std::unordered_set< std::string > selNames;
if(!doOverload) {
checkDeclaration(constructorName, CHECK_UNDECLARED);
}
- defineVar(
- constructorName, constructor, d_globalDeclarations, doOverload);
+ defineVar(constructorName, constructor, globalDecls, doOverload);
consNames.insert(constructorName);
}else{
throw ParserException(constructorName + " already declared in this datatype");
{
checkDeclaration(testerName, CHECK_UNDECLARED);
}
- defineVar(testerName, tester, d_globalDeclarations, doOverload);
+ defineVar(testerName, tester, globalDecls, doOverload);
}
for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++)
{
if(!doOverload) {
checkDeclaration(selectorName, CHECK_UNDECLARED);
}
- defineVar(selectorName, selector, d_globalDeclarations, doOverload);
+ defineVar(selectorName, selector, globalDecls, doOverload);
selNames.insert(selectorName);
}else{
throw ParserException(selectorName + " already declared in this datatype");
void Parser::pushScope(bool bindingLevel)
{
- d_symman->pushScope();
+ d_symman->pushScope(!bindingLevel);
if (!bindingLevel)
{
d_assertionLevel = scopeLevel();
void Parser::reset() { d_symman->reset(); }
+SymbolManager* Parser::getSymbolManager() { return d_symman; }
+
std::vector<unsigned> Parser::processAdHocStringEsc(const std::string& s)
{
std::vector<unsigned> str;
*/
size_t d_assertionLevel;
- /**
- * Whether we're in global declarations mode (all definitions and
- * declarations are global).
- */
- bool d_globalDeclarations;
-
/**
* Maintains a list of reserved symbols at the assertion level that might
* not occur in our symbol table. This is necessary to e.g. support the
virtual void reset();
- void setGlobalDeclarations(bool flag) {
- d_globalDeclarations = flag;
- }
-
- bool getGlobalDeclarations() { return d_globalDeclarations; }
-
- inline SymbolTable* getSymbolTable() const {
- return d_symtab;
- }
+ /** Return the symbol manager used by this parser. */
+ SymbolManager* getSymbolManager();
//------------------------ operator overloading
/** is this function overloaded? */
#define PARSER_STATE ((Smt2*)PARSER->super)
#undef SOLVER
#define SOLVER PARSER_STATE->getSolver()
+#undef SYM_MAN
+#define SYM_MAN PARSER_STATE->getSymbolManager()
#undef MK_TERM
#define MK_TERM SOLVER->mkTerm
#define UNSUPPORTED PARSER_STATE->unimplementedFeature
api::Term func = PARSER_STATE->bindVar(name, t,
ExprManager::VAR_FLAG_DEFINED, true);
cmd->reset(new DefineFunctionCommand(
- name, func, terms, expr, PARSER_STATE->getGlobalDeclarations()));
+ name, func, terms, expr, SYM_MAN->getGlobalDeclarations()));
}
| DECLARE_DATATYPE_TOK datatypeDefCommand[false, cmd]
| DECLARE_DATATYPES_TOK datatypesDefCommand[false, cmd]
// Ugly that this changes the state of the parser; but
// global-declarations affects parsing, so we can't hold off
// on this until some SmtEngine eventually (if ever) executes it.
- if(name == ":global-declarations") {
- PARSER_STATE->setGlobalDeclarations(sexpr.getValue() == "true");
+ if(name == ":global-declarations")
+ {
+ SYM_MAN->setGlobalDeclarations(sexpr.getValue() == "true");
}
}
;
expr = PARSER_STATE->mkHoApply( expr, flattenVars );
}
cmd->reset(new DefineFunctionRecCommand(
- func, bvs, expr, PARSER_STATE->getGlobalDeclarations()));
+ func, bvs, expr, SYM_MAN->getGlobalDeclarations()));
}
| DEFINE_FUNS_REC_TOK
{ PARSER_STATE->checkThatLogicIsSet();}
"define-funs-rec"));
}
cmd->reset(new DefineFunctionRecCommand(
- funcs, formals, func_defs, PARSER_STATE->getGlobalDeclarations()));
+ funcs, formals, func_defs, SYM_MAN->getGlobalDeclarations()));
}
;
api::Term func = PARSER_STATE->bindVar(name, e.getSort(),
ExprManager::VAR_FLAG_DEFINED);
cmd->reset(new DefineFunctionCommand(
- name, func, e, PARSER_STATE->getGlobalDeclarations()));
+ name, func, e, SYM_MAN->getGlobalDeclarations()));
}
| // (define (f (v U) ...) t)
LPAREN_TOK
api::Term func = PARSER_STATE->bindVar(name, tt,
ExprManager::VAR_FLAG_DEFINED);
cmd->reset(new DefineFunctionCommand(
- name, func, terms, e, PARSER_STATE->getGlobalDeclarations()));
+ name, func, terms, e, SYM_MAN->getGlobalDeclarations()));
}
)
| // (define-const x U t)
api::Term func = PARSER_STATE->bindVar(name, t,
ExprManager::VAR_FLAG_DEFINED);
cmd->reset(new DefineFunctionCommand(
- name, func, terms, e, PARSER_STATE->getGlobalDeclarations()));
+ name, func, terms, e, SYM_MAN->getGlobalDeclarations()));
}
| SIMPLIFY_TOK { PARSER_STATE->checkThatLogicIsSet(); }
func,
std::vector<api::Term>(),
expr,
- PARSER_STATE->getGlobalDeclarations());
+ SYM_MAN->getGlobalDeclarations());
c->setMuted(true);
PARSER_STATE->preemptCommand(c);
}