LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/expr - non_closed_node_converter.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 49 56 87.5 %
Date: 2026-02-25 11:44:22 Functions: 5 7 71.4 %
Branches: 25 30 83.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2025 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                 :            :  * Implementation of non-closed node conversion
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "expr/non_closed_node_converter.h"
      17                 :            : 
      18                 :            : #include "expr/array_store_all.h"
      19                 :            : #include "expr/node_algorithm.h"
      20                 :            : #include "expr/skolem_manager.h"
      21                 :            : #include "options/arrays_options.h"
      22                 :            : #include "smt/env.h"
      23                 :            : #include "theory/strings/theory_strings_utils.h"
      24                 :            : #include "theory/uf/function_const.h"
      25                 :            : 
      26                 :            : namespace cvc5::internal {
      27                 :            : 
      28                 :         41 : NonClosedNodeConverter::NonClosedNodeConverter(Env& env)
      29                 :         41 :     : EnvObj(env), NodeConverter(nodeManager())
      30                 :            : {
      31                 :         41 :   getNonClosedKinds(env, d_nonClosedKinds);
      32                 :         41 : }
      33                 :            : 
      34                 :         41 : NonClosedNodeConverter::~NonClosedNodeConverter() {}
      35                 :            : 
      36                 :        412 : Node NonClosedNodeConverter::postConvert(Node n)
      37                 :            : {
      38         [ +  - ]:        412 :   Trace("non-closed-debug") << "postConvert: " << n << std::endl;
      39                 :        412 :   Kind k = n.getKind();
      40                 :        412 :   bool purify = false;
      41         [ +  + ]:        412 :   if (d_nonClosedKinds.find(k) != d_nonClosedKinds.end())
      42                 :            :   {
      43                 :         29 :     purify = true;
      44                 :            :   }
      45         [ -  + ]:        383 :   else if (k == Kind::STORE_ALL)
      46                 :            :   {
      47                 :            :     // Store all hides its element. if this is not closed, then this entire
      48                 :            :     // term must be purified.
      49                 :          0 :     Node nval = n.getConst<ArrayStoreAll>().getValue();
      50                 :          0 :     Node nvalc = convert(nval);
      51         [ -  - ]:          0 :     if (nvalc != nval)
      52                 :            :     {
      53                 :          0 :       purify = true;
      54                 :            :     }
      55                 :          0 :   }
      56                 :            :   else
      57                 :            :   {
      58                 :            :     // node that can "hide" constants, we must convert these to their expanded
      59                 :            :     // form and see if they convert
      60                 :        383 :     Node nc;
      61         [ +  + ]:        383 :     if (k == Kind::CONST_SEQUENCE)
      62                 :            :     {
      63                 :         15 :       nc = theory::strings::utils::mkConcatForConstSequence(n);
      64                 :            :     }
      65         [ +  + ]:        368 :     else if (k == Kind::FUNCTION_ARRAY_CONST)
      66                 :            :     {
      67                 :          3 :       nc = theory::uf::FunctionConst::toLambda(n);
      68                 :            :     }
      69 [ +  + ][ +  + ]:        383 :     if (!nc.isNull() && nc!=n)
                 [ +  + ]
      70                 :            :     {
      71                 :          9 :       Node nnc = convert(nc);
      72         [ +  + ]:          9 :       if (nnc != nc)
      73                 :            :       {
      74                 :          1 :         return nnc;
      75                 :            :       }
      76         [ +  + ]:          9 :     }
      77         [ +  + ]:        383 :   }
      78         [ +  + ]:        411 :   if (purify)
      79                 :            :   {
      80                 :         29 :     Node sk = SkolemManager::mkPurifySkolem(n);
      81                 :         29 :     d_purifySkolems.push_back(sk);
      82                 :         29 :     return sk;
      83                 :         29 :   }
      84                 :        382 :   return n;
      85                 :            : }
      86                 :            : 
      87                 :        353 : bool NonClosedNodeConverter::isClosed(Env& env, const Node& n)
      88                 :            : {
      89                 :        353 :   std::unordered_set<Kind, kind::KindHashFunction> ncks;
      90                 :        353 :   getNonClosedKinds(env, ncks);
      91                 :            :   // additional kinds that *might* be non-closed
      92                 :        353 :   ncks.insert(Kind::STORE_ALL);
      93                 :        353 :   ncks.insert(Kind::CONST_SEQUENCE);
      94                 :        353 :   ncks.insert(Kind::FUNCTION_ARRAY_CONST);
      95                 :            :   // most of the time, this will return true
      96         [ +  + ]:        353 :   if (!expr::hasSubtermKinds(ncks, n))
      97                 :            :   {
      98                 :        312 :     return true;
      99                 :            :   }
     100                 :            :   // otherwise see if it converts, if it doesn't then it is closed
     101                 :         41 :   NonClosedNodeConverter ncnc(env);
     102                 :         41 :   Node nc = ncnc.convert(n);
     103                 :         41 :   return nc == n;
     104                 :        353 : }
     105                 :            : 
     106                 :        394 : void NonClosedNodeConverter::getNonClosedKinds(
     107                 :            :     const Env& env, std::unordered_set<Kind, kind::KindHashFunction>& ncks)
     108                 :            : {
     109                 :            :   // some kinds may appear in model values that cannot be asserted
     110         [ +  - ]:        394 :   if (!env.getOptions().arrays.arraysExp)
     111                 :            :   {
     112                 :        394 :     ncks.insert(Kind::STORE_ALL);
     113                 :            :   }
     114                 :        394 :   ncks.insert(Kind::CODATATYPE_BOUND_VARIABLE);
     115                 :        394 :   ncks.insert(Kind::UNINTERPRETED_SORT_VALUE);
     116                 :            :   // may appear in certain models e.g. strings of excessive length
     117                 :        394 :   ncks.insert(Kind::WITNESS);
     118                 :        394 :   ncks.insert(Kind::REAL_ALGEBRAIC_NUMBER);
     119                 :        394 : }
     120                 :            : 
     121                 :          0 : const std::vector<Node>& NonClosedNodeConverter::getSkolems() const
     122                 :            : {
     123                 :          0 :   return d_purifySkolems;
     124                 :            : }
     125                 :            : 
     126                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14