Eliminate CDHashMap::insertAtContextLevelZero (#8173)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Wed, 2 Mar 2022 21:11:05 +0000 (15:11 -0600)
committerGitHub <noreply@github.com>
Wed, 2 Mar 2022 21:11:05 +0000 (21:11 +0000)
This method unnecessarily complicates the usage of CDHashMap. It had one usage in the current code, for dealing with global declarations. However, this was an entirely artificial use case, as one should properly manage scopes when this option is true (i.e. global-declarations simply disables user-level scoping in the symbol table).

It also simplifies the symbol table so that it doesn't automatically push a global outermost scope. Instead, this scope is pushed when the logic is declared, so that background symbols are correctly added at level 0.

Fixes #4767.

13 files changed:
src/context/cdhashmap.h
src/context/cdhashset.h
src/context/cdinsert_hashmap.h
src/expr/symbol_manager.cpp
src/expr/symbol_table.cpp
src/expr/symbol_table.h
src/parser/parser.cpp
src/parser/parser.h
src/parser/smt2/Smt2.g
src/parser/smt2/smt2.cpp
src/parser/tptp/tptp.cpp
src/parser/tptp/tptp.h
test/unit/context/cdhashmap_black.cpp

index d765905d6632db0ec83c3b42ee994826b53863d0..63b166d6117bebd5658db9c29654ac0cb49b0b80 100644 (file)
@@ -203,28 +203,16 @@ class CDOhash_map : public ContextObj
   CDOhash_map(Context* context,
               CDHashMap<Key, Data, HashFcn>* map,
               const Key& key,
-              const Data& data,
-              bool atLevelZero = false)
+              const Data& data)
       : ContextObj(false, context), d_value(key, data), d_map(NULL)
   {
-    if (atLevelZero)
-    {
-      // "Initializing" map insertion: this entry will never be
-      // removed from the map, it's inserted at level 0 as an
-      // "initializing" element.  See
-      // CDHashMap<>::insertAtContextLevelZero().
-      mutable_data() = data;
-    }
-    else
-    {
-      // Normal map insertion: first makeCurrent(), then set the data
-      // and then, later, the map.  Order is important; we can't
-      // initialize d_map in the constructor init list above, because
-      // we want the restore of d_map to NULL to signal us to remove
-      // the element from the map.
+    // Normal map insertion: first makeCurrent(), then set the data
+    // and then, later, the map.  Order is important; we can't
+    // initialize d_map in the constructor init list above, because
+    // we want the restore of d_map to NULL to signal us to remove
+    // the element from the map.
 
-      set(data);
-    }
+    set(data);
     d_map = map;
 
     CDOhash_map*& first = d_map->d_first;
@@ -379,39 +367,6 @@ class CDHashMap : public ContextObj
     return res.second;
   }
 
-  /**
-   * Version of insert() for CDHashMap<> that inserts data value d at
-   * context level zero.  This is a special escape hatch for inserting
-   * "initializing" data into the map.  Imagine something happens at a
-   * deep context level L that causes insertion into a map, such that
-   * the object should have an "initializing" value v1 below context
-   * level L, and a "current" value v2 at context level L.  Then you
-   * can (assuming key k):
-   *
-   *   map.insertAtContextLevelZero(k, v1);
-   *   map.insert(k, v2);
-   *
-   * The justification for this "escape hatch" has to do with
-   * variables and assignments in theories (e.g., in arithmetic).
-   * Let's say you introduce a new variable x at some deep decision
-   * level (thanks to lazy registration, or a splitting lemma, or
-   * whatever).  x might be mapped to something, but for theory
-   * implementation simplicity shouldn't disappear from the map on
-   * backjump; rather, it can take another (legal) value, or a special
-   * value to indicate it needs to be recomputed.
-   *
-   * It is an error (checked via AlwaysAssert()) to
-   * insertAtContextLevelZero() a key that already is in the map.
-   */
-  void insertAtContextLevelZero(const Key& k, const Data& d)
-  {
-    AlwaysAssert(d_map.find(k) == d_map.end());
-
-    Element* obj =
-        new (true) Element(d_context, this, k, d, true /* atLevelZero */);
-    d_map.insert(std::make_pair(k, obj));
-  }
-
   // FIXME: no erase(), too much hassle to implement efficiently...
 
   using value_type = typename CDOhash_map<Key, Data, HashFcn>::value_type;
index b7e3b8ed59a29bb73e7aa64bbe2ebed1cc528673..cd57d8f765c05113cc7891452c19c540865d2a7e 100644 (file)
@@ -149,10 +149,6 @@ public:
     return super::key_end();
   }
 
-  void insertAtContextLevelZero(const V& v) {
-    return super::insertAtContextLevelZero(v, true);
-  }
-
 }; /* class CDHashSet */
 
 }  // namespace context
index b383fe931dd7fc8c6823d7ec3d443d30a8d75b7f..2d4906ea45c5cd5f5950f36bd1b562878378e1f0 100644 (file)
@@ -28,7 +28,6 @@
  * - Use insert_safe if you want to check if the element has been inserted
  *   and only insert if it has not yet been.
  * - Does not accept TNodes as keys.
- * - Supports insertAtContextLevelZero() if the element is not in the map.
  */
 
 #include <deque>
@@ -191,22 +190,13 @@ private:
   /** For restores, we need to keep track of the previous size. */
   size_t d_size;
 
-  /**
-   * To support insertAtContextLevelZero() and restores,
-   * we have called d_insertMap->d_pushFront().
-   */
-  size_t d_pushFronts;
-
   /**
    * Private copy constructor used only by save().  d_insertMap is
    * not copied: only the base class information and
-   * d_size and d_pushFronts are needed in restore.
+   * d_size are needed in restore.
    */
-  CDInsertHashMap(const CDInsertHashMap& l) :
-    ContextObj(l),
-    d_insertMap(NULL),
-    d_size(l.d_size),
-    d_pushFronts(l.d_pushFronts)
+  CDInsertHashMap(const CDInsertHashMap& l)
+      : ContextObj(l), d_insertMap(nullptr), d_size(l.d_size)
   {
     Debug("CDInsertHashMap") << "copy ctor: " << this
                     << " from " << &l
@@ -232,12 +222,12 @@ private:
     return data;
   }
 protected:
 /**
-   * Implementation of mandatory ContextObj method restore:
-   * restore to the previous size taking into account the number
-   * of new pushFront calls have happened since saving.
-   * The d_insertMap is untouched and d_pushFronts is also kept.
-   */
+ /**
+  * Implementation of mandatory ContextObj method restore:
+  * restore to the previous size taking into account the number
+  * of new pushFront calls have happened since saving.
+  * The d_insertMap is untouched.
+  */
  void restore(ContextObj* data) override
  {
    Debug("CDInsertHashMap")
@@ -245,12 +235,9 @@ protected:
        << " data == " << data << " d_insertMap == " << this->d_insertMap
        << std::endl;
    size_t oldSize = ((CDInsertHashMap<Key, Data, HashFcn>*)data)->d_size;
-   size_t oldPushFronts =
-       ((CDInsertHashMap<Key, Data, HashFcn>*)data)->d_pushFronts;
-   Assert(oldPushFronts <= d_pushFronts);
 
    // The size to restore to.
-   size_t restoreSize = oldSize + (d_pushFronts - oldPushFronts);
+   size_t restoreSize = oldSize;
    d_insertMap->pop_to_size(restoreSize);
    d_size = restoreSize;
    Assert(d_insertMap->size() == d_size);
@@ -263,13 +250,11 @@ public:
  /**
    * Main constructor: d_insertMap starts as an empty map, with the size is 0
    */
-  CDInsertHashMap(Context* context) :
-    ContextObj(context),
-    d_insertMap(new IHM()),
-    d_size(0),
-    d_pushFronts(0){
-    Assert(d_insertMap->size() == d_size);
-  }
+ CDInsertHashMap(Context* context)
+     : ContextObj(context), d_insertMap(new IHM()), d_size(0)
+ {
+   Assert(d_insertMap->size() == d_size);
+ }
 
   /**
    * Destructor: delete the d_insertMap
@@ -328,20 +313,6 @@ public:
     }
   }
 
-  /**
-   * Version of insert() for CDMap<> that inserts data value d at
-   * context level zero.
-   *
-   * It is an error to insertAtContextLevelZero()
-   * a key that already is in the map.
-   */
-  void insertAtContextLevelZero(const Key& k, const Data& d){
-    makeCurrent();
-    ++d_size;
-    ++d_pushFronts;
-    d_insertMap->push_front(k, d);
-  }
-
   /** Returns true if k is a mapped key in the context. */
   bool contains(const Key& k) const {
     return d_insertMap->contains(k);
index 240e043c626d1878de2206e720caae37266bf51b..aaadeeede00780070438889cbe293c8831bf4a5f 100644 (file)
@@ -417,6 +417,7 @@ const std::string& SymbolManager::getLastSynthName() const
 
 void SymbolManager::reset()
 {
+  // reset resets the symbol table even when global declarations are true
   d_symtabAllocated.reset();
   d_implementation->reset();
 }
@@ -424,7 +425,10 @@ void SymbolManager::reset()
 void SymbolManager::resetAssertions()
 {
   d_implementation->resetAssertions();
-  d_symtabAllocated.resetAssertions();
+  if (!d_globalDeclarations)
+  {
+    d_symtabAllocated.resetAssertions();
+  }
 }
 
 }  // namespace cvc5
index 762120b5b619316229765261a293968e6ce90a4e..c74548d9719d4db7f19c7f8fd3897724139d3892 100644 (file)
@@ -342,18 +342,15 @@ class SymbolTable::Implementation {
         d_typeMap(&d_context),
         d_overload_trie(&d_context)
   {
-    // use an outermost push, to be able to clear definitions not at level zero
-    d_context.push();
   }
 
-  ~Implementation() { d_context.pop(); }
+  ~Implementation() {}
 
-  bool bind(const string& name, api::Term obj, bool levelZero, bool doOverload);
-  void bindType(const string& name, api::Sort t, bool levelZero = false);
+  bool bind(const string& name, api::Term obj, bool doOverload);
+  void bindType(const string& name, api::Sort t);
   void bindType(const string& name,
                 const vector<api::Sort>& params,
-                api::Sort t,
-                bool levelZero = false);
+                api::Sort t);
   bool isBound(const string& name) const;
   bool isBoundType(const string& name) const;
   api::Term lookup(const string& name) const;
@@ -405,23 +402,18 @@ class SymbolTable::Implementation {
 
 bool SymbolTable::Implementation::bind(const string& name,
                                        api::Term obj,
-                                       bool levelZero,
                                        bool doOverload)
 {
   PrettyCheckArgument(!obj.isNull(), obj, "cannot bind to a null api::Term");
   Trace("sym-table") << "SymbolTable: bind " << name
-                     << ", levelZero=" << levelZero
                      << ", doOverload=" << doOverload << std::endl;
   if (doOverload) {
     if (!bindWithOverloading(name, obj)) {
       return false;
     }
   }
-  if (levelZero) {
-    d_exprMap.insertAtContextLevelZero(name, obj);
-  } else {
     d_exprMap.insert(name, obj);
-  }
+
   return true;
 }
 
@@ -440,21 +432,14 @@ api::Term SymbolTable::Implementation::lookup(const string& name) const
   }
 }
 
-void SymbolTable::Implementation::bindType(const string& name,
-                                           api::Sort t,
-                                           bool levelZero)
+void SymbolTable::Implementation::bindType(const string& name, api::Sort t)
 {
-  if (levelZero) {
-    d_typeMap.insertAtContextLevelZero(name, make_pair(vector<api::Sort>(), t));
-  } else {
     d_typeMap.insert(name, make_pair(vector<api::Sort>(), t));
-  }
 }
 
 void SymbolTable::Implementation::bindType(const string& name,
                                            const vector<api::Sort>& params,
-                                           api::Sort t,
-                                           bool levelZero)
+                                           api::Sort t)
 {
   if (Debug.isOn("sort")) {
     Debug("sort") << "bindType(" << name << ", [";
@@ -466,11 +451,8 @@ void SymbolTable::Implementation::bindType(const string& name,
     }
     Debug("sort") << "], " << t << ")" << endl;
   }
-  if (levelZero) {
-    d_typeMap.insertAtContextLevelZero(name, make_pair(params, t));
-  } else {
+
     d_typeMap.insert(name, make_pair(params, t));
-  }
 }
 
 bool SymbolTable::Implementation::isBoundType(const string& name) const {
@@ -542,7 +524,7 @@ size_t SymbolTable::Implementation::lookupArity(const string& name) {
 
 void SymbolTable::Implementation::popScope() {
   // should not pop beyond level one
-  if (d_context.getLevel() == 1)
+  if (d_context.getLevel() == 0)
   {
     throw ScopeException();
   }
@@ -627,23 +609,21 @@ SymbolTable::SymbolTable() : d_implementation(new SymbolTable::Implementation())
 SymbolTable::~SymbolTable() {}
 bool SymbolTable::bind(const string& name,
                        api::Term obj,
-                       bool levelZero,
                        bool doOverload)
 {
-  return d_implementation->bind(name, obj, levelZero, doOverload);
+  return d_implementation->bind(name, obj, doOverload);
 }
 
-void SymbolTable::bindType(const string& name, api::Sort t, bool levelZero)
+void SymbolTable::bindType(const string& name, api::Sort t)
 {
-  d_implementation->bindType(name, t, levelZero);
+  d_implementation->bindType(name, t);
 }
 
 void SymbolTable::bindType(const string& name,
                            const vector<api::Sort>& params,
-                           api::Sort t,
-                           bool levelZero)
+                           api::Sort t)
 {
-  d_implementation->bindType(name, params, t, levelZero);
+  d_implementation->bindType(name, params, t);
 }
 
 bool SymbolTable::isBound(const string& name) const
index ddf26f9da89c8902e45421bcd44333ba59d26bfe..e4a39a8cac4f2258a595d59a9dc0c456bc0ee9cb 100644 (file)
@@ -66,14 +66,12 @@ class CVC5_EXPORT SymbolTable
    *
    * @param name an identifier
    * @param obj the expression to bind to <code>name</code>
-   * @param levelZero set if the binding must be done at level 0
    * @param doOverload set if the binding can overload the function name.
    *
    * Returns false if the binding was invalid.
    */
   bool bind(const std::string& name,
             api::Term obj,
-            bool levelZero = false,
             bool doOverload = false);
 
   /**
@@ -85,9 +83,8 @@ class CVC5_EXPORT SymbolTable
    *
    * @param name an identifier
    * @param t the type to bind to <code>name</code>
-   * @param levelZero set if the binding must be done at level 0
    */
-  void bindType(const std::string& name, api::Sort t, bool levelZero = false);
+  void bindType(const std::string& name, api::Sort t);
 
   /**
    * Bind a type to a name in the current scope.  If <code>name</code>
@@ -99,13 +96,10 @@ class CVC5_EXPORT SymbolTable
    * @param name an identifier
    * @param params the parameters to the type
    * @param t the type to bind to <code>name</code>
-   * @param levelZero true to bind it globally (default is to bind it
-   * locally within the current scope)
    */
   void bindType(const std::string& name,
                 const std::vector<api::Sort>& params,
-                api::Sort t,
-                bool levelZero = false);
+                api::Sort t);
 
   /**
    * Check whether a name is bound to an expression with bind().
index 580c74f0fa8f74d159295fde31f7e35df4047de4..6c04a3ad67fead1f4bbdaeb73302cce82b3a9da1 100644 (file)
@@ -202,13 +202,11 @@ bool Parser::isPredicate(const std::string& name) {
 
 api::Term Parser::bindVar(const std::string& name,
                           const api::Sort& type,
-                          bool levelZero,
                           bool doOverload)
 {
-  bool globalDecls = d_symman->getGlobalDeclarations();
   Debug("parser") << "bindVar(" << name << ", " << type << ")" << std::endl;
   api::Term expr = d_solver->mkConst(type, name);
-  defineVar(name, expr, globalDecls || levelZero, doOverload);
+  defineVar(name, expr, doOverload);
   return expr;
 }
 
@@ -234,12 +232,11 @@ std::vector<api::Term> Parser::bindBoundVars(
 
 std::vector<api::Term> Parser::bindVars(const std::vector<std::string> names,
                                         const api::Sort& type,
-                                        bool levelZero,
                                         bool doOverload)
 {
   std::vector<api::Term> vars;
   for (unsigned i = 0; i < names.size(); ++i) {
-    vars.push_back(bindVar(names[i], type, levelZero, doOverload));
+    vars.push_back(bindVar(names[i], type, doOverload));
   }
   return vars;
 }
@@ -256,11 +253,10 @@ std::vector<api::Term> Parser::bindBoundVars(
 
 void Parser::defineVar(const std::string& name,
                        const api::Term& val,
-                       bool levelZero,
                        bool doOverload)
 {
   Debug("parser") << "defineVar( " << name << " := " << val << ")" << std::endl;
-  if (!d_symtab->bind(name, val, levelZero, doOverload))
+  if (!d_symtab->bind(name, val, doOverload))
   {
     std::stringstream ss;
     ss << "Cannot bind " << name << " to symbol of type " << val.getSort();
@@ -272,7 +268,6 @@ void Parser::defineVar(const std::string& name,
 
 void Parser::defineType(const std::string& name,
                         const api::Sort& type,
-                        bool levelZero,
                         bool skipExisting)
 {
   if (skipExisting && isDeclared(name, SYM_SORT))
@@ -280,16 +275,15 @@ void Parser::defineType(const std::string& name,
     Assert(d_symtab->lookupType(name) == type);
     return;
   }
-  d_symtab->bindType(name, type, levelZero);
+  d_symtab->bindType(name, type);
   Assert(isDeclared(name, SYM_SORT));
 }
 
 void Parser::defineType(const std::string& name,
                         const std::vector<api::Sort>& params,
-                        const api::Sort& type,
-                        bool levelZero)
+                        const api::Sort& type)
 {
-  d_symtab->bindType(name, params, type, levelZero);
+  d_symtab->bindType(name, params, type);
   Assert(isDeclared(name, SYM_SORT));
 }
 
@@ -314,9 +308,8 @@ void Parser::defineParameterizedType(const std::string& name,
 api::Sort Parser::mkSort(const std::string& name)
 {
   Debug("parser") << "newSort(" << name << ")" << std::endl;
-  bool globalDecls = d_symman->getGlobalDeclarations();
   api::Sort type = d_solver->mkUninterpretedSort(name);
-  defineType(name, type, globalDecls);
+  defineType(name, type);
   return type;
 }
 
@@ -324,9 +317,8 @@ api::Sort Parser::mkSortConstructor(const std::string& name, size_t arity)
 {
   Debug("parser") << "newSortConstructor(" << name << ", " << arity << ")"
                   << std::endl;
-  bool globalDecls = d_symman->getGlobalDeclarations();
   api::Sort type = d_solver->mkSortConstructorSort(name, arity);
-  defineType(name, vector<api::Sort>(arity), type, globalDecls);
+  defineType(name, vector<api::Sort>(arity), type);
   return type;
 }
 
@@ -383,7 +375,6 @@ std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
         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];
@@ -396,11 +387,11 @@ std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
       if (t.isParametricDatatype())
       {
         std::vector<api::Sort> paramTypes = t.getDatatypeParamSorts();
-        defineType(name, paramTypes, t, globalDecls);
+        defineType(name, paramTypes, t);
       }
       else
       {
-        defineType(name, t, globalDecls);
+        defineType(name, t);
       }
       std::unordered_set< std::string > consNames;
       std::unordered_set< std::string > selNames;
@@ -414,7 +405,7 @@ std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
           if(!doOverload) {
             checkDeclaration(constructorName, CHECK_UNDECLARED);
           }
-          defineVar(constructorName, constructor, globalDecls, doOverload);
+          defineVar(constructorName, constructor, doOverload);
           consNames.insert(constructorName);
         }else{
           throw ParserException(constructorName + " already declared in this datatype");
@@ -428,7 +419,7 @@ std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
           {
             checkDeclaration(testerName, CHECK_UNDECLARED);
           }
-          defineVar(testerName, tester, globalDecls, doOverload);
+          defineVar(testerName, tester, doOverload);
         }
         for (size_t k = 0, nargs = ctor.getNumSelectors(); k < nargs; k++)
         {
@@ -440,7 +431,7 @@ std::vector<api::Sort> Parser::bindMutualDatatypeTypes(
             if(!doOverload) {
               checkDeclaration(selectorName, CHECK_UNDECLARED);
             }
-            defineVar(selectorName, selector, globalDecls, doOverload);
+            defineVar(selectorName, selector, doOverload);
             selNames.insert(selectorName);
           }else{
             throw ParserException(selectorName + " already declared in this datatype");
index 43edbf299144278fc68aed9c20f91c6a52b58a08..6781fc4f99b3f6bf3a286f42c0e221311419390f 100644 (file)
@@ -389,9 +389,6 @@ public:
   void checkFunctionLike(api::Term fun);
 
   /** Create a new cvc5 variable expression of the given type.
-   *
-   * It is inserted at context level zero in the symbol table if levelZero is
-   * true, or if we are using global declarations.
    *
    * If a symbol with name already exists,
    *  then if doOverload is true, we create overloaded operators.
@@ -400,15 +397,11 @@ public:
    */
   api::Term bindVar(const std::string& name,
                     const api::Sort& type,
-                    bool levelZero = false,
                     bool doOverload = false);
 
   /**
    * Create a set of new cvc5 variable expressions of the given type.
    *
-   * It is inserted at context level zero in the symbol table if levelZero is
-   * true, or if we are using global declarations.
-   *
    * For each name, if a symbol with name already exists,
    *  then if doOverload is true, we create overloaded operators.
    *  else if doOverload is false, the existing expression is shadowed by the
@@ -416,7 +409,6 @@ public:
    */
   std::vector<api::Term> bindVars(const std::vector<std::string> names,
                                   const api::Sort& type,
-                                  bool levelZero = false,
                                   bool doOverload = false);
 
   /**
@@ -444,7 +436,6 @@ public:
                                        const api::Sort& type);
 
   /** Create a new variable definition (e.g., from a let binding).
-   * levelZero is set if the binding must be done at level 0.
    * If a symbol with name already exists,
    *  then if doOverload is true, we create overloaded operators.
    *  else if doOverload is false, the existing expression is shadowed by the
@@ -452,7 +443,6 @@ public:
    */
   void defineVar(const std::string& name,
                  const api::Term& val,
-                 bool levelZero = false,
                  bool doOverload = false);
 
   /**
@@ -460,15 +450,12 @@ public:
    *
    * @param name The name of the type
    * @param type The type that should be associated with the name
-   * @param levelZero If true, the type definition is considered global and
-   *                  cannot be removed by popping the user context
    * @param skipExisting If true, the type definition is ignored if the same
    *                     symbol has already been defined. It is assumed that
    *                     the definition is the exact same as the existing one.
    */
   void defineType(const std::string& name,
                   const api::Sort& type,
-                  bool levelZero = false,
                   bool skipExisting = false);
 
   /**
@@ -477,13 +464,10 @@ public:
    * @param name The name of the type
    * @param params The type parameters
    * @param type The type that should be associated with the name
-   * @param levelZero If true, the type definition is considered global and
-   *                  cannot be removed by poppoing the user context
    */
   void defineType(const std::string& name,
                   const std::vector<api::Sort>& params,
-                  const api::Sort& type,
-                  bool levelZero = false);
+                  const api::Sort& type);
 
   /** Create a new type definition (e.g., from an SMT-LIBv2 define-sort). */
   void defineParameterizedType(const std::string& name,
index e19a78c84afc272c3b183d13993bf69522a1273c..355a3469e44934b774c1b6f87ac418654c4ebbd7 100644 (file)
@@ -287,7 +287,7 @@ command [std::unique_ptr<cvc5::Command>* cmd]
       else
       {
         api::Term func =
-            PARSER_STATE->bindVar(name, t, false, true);
+            PARSER_STATE->bindVar(name, t, true);
         cmd->reset(new DeclareFunctionCommand(name, func, t));
       }
     }
@@ -781,7 +781,7 @@ smt25Command[std::unique_ptr<cvc5::Command>* cmd]
                                       "version 2.0");
       }
       api::Term c =
-          PARSER_STATE->bindVar(name, t, false, true);
+          PARSER_STATE->bindVar(name, t, true);
       cmd->reset(new DeclareFunctionCommand(name, c, t)); }
 
     /* get model */
@@ -947,7 +947,7 @@ extendedCommand[std::unique_ptr<cvc5::Command>* cmd]
         }
         // allow overloading
         api::Term func =
-            PARSER_STATE->bindVar(name, tt, false, true);
+            PARSER_STATE->bindVar(name, tt, true);
         seq->addCommand(new DeclareFunctionCommand(name, func, tt));
         sorts.clear();
       }
@@ -967,7 +967,7 @@ extendedCommand[std::unique_ptr<cvc5::Command>* cmd]
         }
         // allow overloading
         api::Term func =
-            PARSER_STATE->bindVar(name, t, false, true);
+            PARSER_STATE->bindVar(name, t, true);
         seq->addCommand(new DeclareFunctionCommand(name, func, t));
         sorts.clear();
       }
index 0f0e3060c6a0c4fa640a65eda03a9aa4394d23de..ec83dff0b1d864307a848b2a36df2670613837d2 100644 (file)
@@ -277,9 +277,9 @@ void Smt2::addSepOperators() {
 
 void Smt2::addCoreSymbols()
 {
-  defineType("Bool", d_solver->getBooleanSort(), true, true);
-  defineVar("true", d_solver->mkTrue(), true, true);
-  defineVar("false", d_solver->mkFalse(), true, true);
+  defineType("Bool", d_solver->getBooleanSort(), true);
+  defineVar("true", d_solver->mkTrue(), true);
+  defineVar("false", d_solver->mkFalse(), true);
   addOperator(api::AND, "and");
   addOperator(api::DISTINCT, "distinct");
   addOperator(api::EQUAL, "=");
@@ -410,7 +410,7 @@ api::Term Smt2::bindDefineFunRec(
   api::Sort ft = mkFlatFunctionType(sorts, t, flattenVars);
 
   // allow overloading
-  return bindVar(fname, ft, false, true);
+  return bindVar(fname, ft, true);
 }
 
 void Smt2::pushDefineFunRecScope(
@@ -513,7 +513,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
 
   if(d_logic.isTheoryEnabled(theory::THEORY_ARITH)) {
     if(d_logic.areIntegersUsed()) {
-      defineType("Int", d_solver->getIntegerSort(), true, true);
+      defineType("Int", d_solver->getIntegerSort(), true);
       addArithmeticOperators();
       if (!strictModeEnabled() || !d_logic.isLinear())
       {
@@ -526,7 +526,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
 
     if (d_logic.areRealsUsed())
     {
-      defineType("Real", d_solver->getRealSort(), true, true);
+      defineType("Real", d_solver->getRealSort(), true);
       addArithmeticOperators();
       addOperator(api::DIVISION, "/");
       if (!strictModeEnabled())
@@ -577,7 +577,7 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
 
   if(d_logic.isTheoryEnabled(theory::THEORY_DATATYPES)) {
     const std::vector<api::Sort> types;
-    defineType("Tuple", d_solver->mkTupleSort(types), true, true);
+    defineType("Tuple", d_solver->mkTupleSort(types), true);
     addDatatypesOperators();
   }
 
@@ -632,9 +632,9 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
     addOperator(api::TABLE_PRODUCT, "table.product");
   }
   if(d_logic.isTheoryEnabled(theory::THEORY_STRINGS)) {
-    defineType("String", d_solver->getStringSort(), true, true);
-    defineType("RegLan", d_solver->getRegExpSort(), true, true);
-    defineType("Int", d_solver->getIntegerSort(), true, true);
+    defineType("String", d_solver->getStringSort(), true);
+    defineType("RegLan", d_solver->getRegExpSort(), true);
+    defineType("Int", d_solver->getIntegerSort(), true);
 
     defineVar("re.none", d_solver->mkRegexpNone());
     defineVar("re.allchar", d_solver->mkRegexpAllchar());
@@ -651,11 +651,11 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
   }
 
   if (d_logic.isTheoryEnabled(theory::THEORY_FP)) {
-    defineType("RoundingMode", d_solver->getRoundingModeSort(), true, true);
-    defineType("Float16", d_solver->mkFloatingPointSort(5, 11), true, true);
-    defineType("Float32", d_solver->mkFloatingPointSort(8, 24), true, true);
-    defineType("Float64", d_solver->mkFloatingPointSort(11, 53), true, true);
-    defineType("Float128", d_solver->mkFloatingPointSort(15, 113), true, true);
+    defineType("RoundingMode", d_solver->getRoundingModeSort(), true);
+    defineType("Float16", d_solver->mkFloatingPointSort(5, 11), true);
+    defineType("Float32", d_solver->mkFloatingPointSort(8, 24), true);
+    defineType("Float64", d_solver->mkFloatingPointSort(11, 53), true);
+    defineType("Float128", d_solver->mkFloatingPointSort(15, 113), true);
 
     defineVar("RNE", d_solver->mkRoundingMode(api::ROUND_NEAREST_TIES_TO_EVEN));
     defineVar("roundNearestTiesToEven",
@@ -681,6 +681,10 @@ Command* Smt2::setLogic(std::string name, bool fromCommand)
     addSepOperators();
   }
 
+  // builtin symbols of the logic are declared at context level zero, hence
+  // we push the outermost scope here
+  pushScope(true);
+
   std::string logic = sygus() ? d_logic.getLogicString() : name;
   if (!fromCommand)
   {
index b8f25c66e61e8866a17c65a29b1e2f0d50b81e93..37ef05f7f533c400acddae83d29368b222e62bfe 100644 (file)
@@ -240,20 +240,34 @@ api::Term Tptp::parseOpToExpr(ParseOp& p)
   // if it has a kind, it's a builtin one and this function should not have been
   // called
   Assert(p.d_kind == api::NULL_EXPR);
-  if (isDeclared(p.d_name))
-  {  // already appeared
-    expr = getVariable(p.d_name);
-  }
-  else
+  expr = isTptpDeclared(p.d_name);
+  if (expr.isNull())
   {
     api::Sort t =
         p.d_type == d_solver->getBooleanSort() ? p.d_type : d_unsorted;
-    expr = bindVar(p.d_name, t, true);  // must define at level zero
+    expr = bindVar(p.d_name, t);  // must define at level zero
+    d_auxSymbolTable[p.d_name] = expr;
     preemptCommand(new DeclareFunctionCommand(p.d_name, expr, t));
   }
   return expr;
 }
 
+api::Term Tptp::isTptpDeclared(const std::string& name)
+{
+  if (isDeclared(name))
+  {  // already appeared
+    return getVariable(name);
+  }
+  std::unordered_map<std::string, api::Term>::iterator it =
+      d_auxSymbolTable.find(name);
+  if (it != d_auxSymbolTable.end())
+  {
+    return it->second;
+  }
+  // otherwise null
+  return api::Term();
+}
+
 api::Term Tptp::applyParseOp(ParseOp& p, std::vector<api::Term>& args)
 {
   if (Debug.isOn("parser"))
@@ -281,18 +295,15 @@ api::Term Tptp::applyParseOp(ParseOp& p, std::vector<api::Term>& args)
   if (p.d_kind == api::NULL_EXPR)
   {
     // A non-built-in function application, get the expression
-    api::Term v;
-    if (isDeclared(p.d_name))
-    {  // already appeared
-      v = getVariable(p.d_name);
-    }
-    else
+    api::Term v = isTptpDeclared(p.d_name);
+    if (v.isNull())
     {
       std::vector<api::Sort> sorts(args.size(), d_unsorted);
       api::Sort t =
           p.d_type == d_solver->getBooleanSort() ? p.d_type : d_unsorted;
       t = d_solver->mkFunctionSort(sorts, t);
-      v = bindVar(p.d_name, t, true);  // must define at level zero
+      v = bindVar(p.d_name, t);  // must define at level zero
+      d_auxSymbolTable[p.d_name] = v;
       preemptCommand(new DeclareFunctionCommand(p.d_name, v, t));
     }
     // args might be rationals, in which case we need to create
index 2167a6c3898a925c628930d1801d49ca90510ae5..f765bfb2faeb52735d7909e5a2db29af76e4b44a 100644 (file)
@@ -183,6 +183,8 @@ class Tptp : public Parser {
 
  private:
   void addArithmeticOperators();
+  /** is the name declared, if so, return the term for that name */
+  api::Term isTptpDeclared(const std::string& name);
 
   // In CNF variable are implicitly binded
   // d_freevar collect them
@@ -194,6 +196,13 @@ class Tptp : public Parser {
   // The set of expression that already have a bridge
   std::unordered_set<api::Term> d_r_converted;
   std::unordered_map<std::string, api::Term> d_distinct_objects;
+  /**
+   * TPTP automatically declares symbols as they are parsed inline. This
+   * requires using an auxiliary symbol table for such symbols. This must be
+   * independent of the main symbol table which is aware of quantifier
+   * scopes.
+   */
+  std::unordered_map<std::string, api::Term> d_auxSymbolTable;
 
   std::vector< pANTLR3_INPUT_STREAM > d_in_created;
 
index c4d7449140bd06a7e815f909faf1d3078d4cc3dd..a4060e1f8df1196fb3f1a2a98153194411641692 100644 (file)
@@ -75,11 +75,10 @@ TEST_F(TestContextBlackCDHashMap, simple_sequence)
         d_context->push();
         ASSERT_TRUE(elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}}));
 
-        map.insertAtContextLevelZero(23, 317);
         map.insert(1, 45);
 
         ASSERT_TRUE(
-            elements_are(map, {{1, 45}, {3, 4}, {5, 6}, {9, 8}, {23, 317}}));
+            elements_are(map, {{1, 45}, {3, 4}, {5, 6}, {9, 8}}));
         map.insert(23, 324);
 
         ASSERT_TRUE(
@@ -88,15 +87,15 @@ TEST_F(TestContextBlackCDHashMap, simple_sequence)
       }
 
       ASSERT_TRUE(
-          elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}, {23, 317}}));
+          elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}}));
       d_context->pop();
     }
 
-    ASSERT_TRUE(elements_are(map, {{3, 4}, {5, 6}, {9, 8}, {23, 317}}));
+    ASSERT_TRUE(elements_are(map, {{3, 4}, {5, 6}, {9, 8}}));
     d_context->pop();
   }
 
-  ASSERT_TRUE(elements_are(map, {{3, 4}, {23, 317}}));
+  ASSERT_TRUE(elements_are(map, {{3, 4}}));
 }
 
 TEST_F(TestContextBlackCDHashMap, simple_sequence_fewer_finds)
@@ -155,15 +154,9 @@ TEST_F(TestContextBlackCDHashMap, insert_at_context_level_zero)
 
       ASSERT_TRUE(elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}}));
 
-      map.insertAtContextLevelZero(23, 317);
-
       ASSERT_TRUE(
-          elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}, {23, 317}}));
+          elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}}));
 
-      ASSERT_DEATH(map.insertAtContextLevelZero(23, 317),
-                   "insertAtContextLevelZero");
-      ASSERT_DEATH(map.insertAtContextLevelZero(23, 472),
-                   "insertAtContextLevelZero");
       map.insert(23, 472);
 
       ASSERT_TRUE(
@@ -174,8 +167,6 @@ TEST_F(TestContextBlackCDHashMap, insert_at_context_level_zero)
         ASSERT_TRUE(
             elements_are(map, {{1, 2}, {3, 4}, {5, 6}, {9, 8}, {23, 472}}));
 
-        ASSERT_DEATH(map.insertAtContextLevelZero(23, 0),
-                     "insertAtContextLevelZero");
         map.insert(23, 1024);
 
         ASSERT_TRUE(
@@ -187,19 +178,15 @@ TEST_F(TestContextBlackCDHashMap, insert_at_context_level_zero)
       d_context->pop();
     }
 
-    ASSERT_TRUE(elements_are(map, {{3, 4}, {5, 6}, {9, 8}, {23, 317}}));
+    ASSERT_TRUE(elements_are(map, {{3, 4}, {5, 6}, {9, 8}}));
 
-    ASSERT_DEATH(map.insertAtContextLevelZero(23, 0),
-                 "insertAtContextLevelZero");
     map.insert(23, 477);
 
     ASSERT_TRUE(elements_are(map, {{3, 4}, {5, 6}, {9, 8}, {23, 477}}));
     d_context->pop();
   }
 
-  ASSERT_DEATH(map.insertAtContextLevelZero(23, 0), "insertAtContextLevelZero");
-
-  ASSERT_TRUE(elements_are(map, {{3, 4}, {23, 317}}));
+  ASSERT_TRUE(elements_are(map, {{3, 4}}));
 }
 }  // namespace test
 }  // namespace cvc5