Fix the way abstract values are typed; fixes some compliance issues.
authorMorgan Deters <mdeters@gmail.com>
Sat, 1 Dec 2012 14:36:14 +0000 (14:36 +0000)
committerMorgan Deters <mdeters@gmail.com>
Sat, 1 Dec 2012 14:36:14 +0000 (14:36 +0000)
Also support array-store-all for Boolean terms (related to abstract values, since that's the only way for the user to include an array-store-all in an assertion).

(this commit was certified error- and warning-free by the test-and-commit script.)

src/expr/node_builder.h
src/expr/node_manager.cpp
src/expr/node_manager.h
src/smt/boolean_terms.cpp
src/smt/smt_engine.cpp
src/theory/builtin/theory_builtin_type_rules.h

index e688731768982a11ec69bbd9b34bb8b39c346cc9..f6aa1920d48ca66a93fc1768f606374e36719c24 100644 (file)
@@ -1303,14 +1303,7 @@ inline void NodeBuilder<nchild_thresh>::maybeCheckType(const TNode n) const
     kind::MetaKind mk = n.getMetaKind();
     if( mk != kind::metakind::VARIABLE
         && mk != kind::metakind::CONSTANT ) {
-      try {
-        d_nm->getType(n, true);
-      } catch(UnknownTypeException&) {
-        // Ignore the error; this expression doesn't have a type,
-        // because it has an abstract value in it.  If the user
-        // depends on the type of this expression, he should get an
-        // exception, but so far he's only constructed it.
-      }
+      d_nm->getType(n, true);
     }
   }
 }
index f040c7c726a9e3cb4bb66d61e7e55d520a4d1842..59d23c6ea622d30dd1d86666db780e0ffa83dfc9 100644 (file)
@@ -86,7 +86,8 @@ NodeManager::NodeManager(context::Context* ctxt,
   d_attrManager(ctxt),
   d_exprManager(exprManager),
   d_nodeUnderDeletion(NULL),
-  d_inReclaimZombies(false) {
+  d_inReclaimZombies(false),
+  d_abstractValueCount(0) {
   init();
 }
 
@@ -99,7 +100,8 @@ NodeManager::NodeManager(context::Context* ctxt,
   d_attrManager(ctxt),
   d_exprManager(exprManager),
   d_nodeUnderDeletion(NULL),
-  d_inReclaimZombies(false) {
+  d_inReclaimZombies(false),
+  d_abstractValueCount(0) {
   init();
 }
 
index 2cda23f2d4985258eb32764bb7e97d44a16b0f3c..e94795f0e2b235183f3dfa75853643b41e6d4e18 100644 (file)
@@ -170,6 +170,14 @@ class NodeManager {
    */
   std::hash_map<TypeNode, TypeNode, TypeNodeHashFunction> d_tupleAndRecordTypes;
 
+  /**
+   * Keep a count of all abstract values produced by this NodeManager.
+   * Abstract values have a type attribute, so if multiple SmtEngines
+   * are attached to this NodeManager, we don't want their abstract
+   * values to overlap.
+   */
+  unsigned d_abstractValueCount;
+
   /**
    * Look up a NodeValue in the pool associated to this NodeManager.
    * The NodeValue argument need not be a "completely-constructed"
@@ -455,6 +463,9 @@ public:
   /** Create a instantiation constant with the given type. */
   Node mkInstConstant(const TypeNode& type);
 
+  /** Make a new abstract value with the given type. */
+  Node mkAbstractValue(const TypeNode& type);
+
   /**
    * Create a constant of type T.  It will have the appropriate
    * CONST_* kind defined for T.
@@ -1557,6 +1568,13 @@ inline Node NodeManager::mkInstConstant(const TypeNode& type) {
   return n;
 }
 
+inline Node NodeManager::mkAbstractValue(const TypeNode& type) {
+  Node n = mkConst(AbstractValue(++d_abstractValueCount));
+  n.setAttribute(TypeAttr(), type);
+  n.setAttribute(TypeCheckedAttr(), true);
+  return n;
+}
+
 template <class T>
 Node NodeManager::mkConst(const T& val) {
   return mkConstInternal<Node, T>(val);
index dda9c7a3e7d1cb89a3c9dfaea6140c39f7e27f54..696622cfef5ef6c1484b8aec44a01a4b36fa15da 100644 (file)
@@ -121,6 +121,33 @@ Node BooleanTermConverter::rewriteBooleanTerms(TNode top, bool boolParent) throw
   }
 
   if(mk == kind::metakind::CONSTANT) {
+    if(k == kind::STORE_ALL) {
+      const ArrayStoreAll& asa = top.getConst<ArrayStoreAll>();
+      ArrayType arrType = asa.getType();
+      TypeNode indexType = TypeNode::fromType(arrType.getIndexType());
+      Type constituentType = arrType.getConstituentType();
+      if(constituentType.isBoolean()) {
+        // we have store_all(true) or store_all(false)
+        // just turn it into store_all(1) or store_all(0)
+        Node newConst = nm->mkConst(BitVector(1u, asa.getExpr().getConst<bool>() ? 1u : 0u));
+        if(indexType.isBoolean()) {
+          // change index type to BV(1) also
+          indexType = nm->mkBitVectorType(1);
+        }
+        ArrayStoreAll asaRepl(nm->mkArrayType(indexType, nm->mkBitVectorType(1)).toType(), newConst.toExpr());
+        Node n = nm->mkConst(asaRepl);
+        Debug("boolean-terms") << " returning new store_all: " << n << std::endl;
+        return n;
+      }
+      if(indexType.isBoolean()) {
+        // must change index type to BV(1)
+        indexType = nm->mkBitVectorType(1);
+        ArrayStoreAll asaRepl(nm->mkArrayType(indexType, TypeNode::fromType(constituentType)).toType(), asa.getExpr());
+        Node n = nm->mkConst(asaRepl);
+        Debug("boolean-terms") << " returning new store_all: " << n << std::endl;
+        return n;
+      }
+    }
     return top;
   } else if(mk == kind::metakind::VARIABLE) {
     TypeNode t = top.getType();
index fb8b787594db737378f16983b3723cd6b770c0fd..c82b7ca2c0268306d4000d1f784ac225aa730d40 100644 (file)
@@ -495,7 +495,7 @@ public:
     Assert(options::abstractValues());
     Node& val = d_abstractValues[n];
     if(val.isNull()) {
-      val = d_smt.d_nodeManager->mkConst(AbstractValue(d_abstractValues.size()));
+      val = d_smt.d_nodeManager->mkAbstractValue(n.getType());
       d_abstractValueMap.addSubstitution(val, n);
     }
     return val;
index 40f838623d15142e369be0959a4c199c51dcb873..baf498968f662ba06307aa3a834259e404162bce 100644 (file)
@@ -139,9 +139,9 @@ class AbstractValueTypeRule {
 public:
   inline static TypeNode computeType(NodeManager* nodeManager, TNode n, bool check) {
     // An UnknownTypeException means that this node has no type.  For now,
-    // only abstract values are like this.  Assigning them a type in all
-    // cases is difficult, since then the parser and the SmtEngine must be
-    // more tightly coupled.
+    // only abstract values are like this---and then, only if they are created
+    // by the user and don't actually correspond to one that the SmtEngine gave
+    // them previously.
     throw UnknownTypeException(n);
   }
 };/* class AbstractValueTypeRule */