LCOV - code coverage report
Current view: top level - buildbot/coverage/build/src/proof/lfsc - lfsc_node_converter.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 611 635 96.2 %
Date: 2024-11-08 12:39:45 Functions: 25 26 96.2 %
Branches: 418 541 77.3 %

           Branch data     Line data    Source code
       1                 :            : /******************************************************************************
       2                 :            :  * Top contributors (to current version):
       3                 :            :  *   Andrew Reynolds, Aina Niemetz, Abdalrhman Mohamed
       4                 :            :  *
       5                 :            :  * This file is part of the cvc5 project.
       6                 :            :  *
       7                 :            :  * Copyright (c) 2009-2024 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 LFSC node conversion
      14                 :            :  */
      15                 :            : 
      16                 :            : #include "proof/lfsc/lfsc_node_converter.h"
      17                 :            : 
      18                 :            : #include <algorithm>
      19                 :            : #include <iomanip>
      20                 :            : #include <sstream>
      21                 :            : 
      22                 :            : #include "expr/array_store_all.h"
      23                 :            : #include "expr/cardinality_constraint.h"
      24                 :            : #include "expr/dtype.h"
      25                 :            : #include "expr/dtype_cons.h"
      26                 :            : #include "expr/nary_term_util.h"
      27                 :            : #include "expr/sequence.h"
      28                 :            : #include "expr/skolem_manager.h"
      29                 :            : #include "printer/smt2/smt2_printer.h"
      30                 :            : #include "theory/builtin/generic_op.h"
      31                 :            : #include "theory/bv/theory_bv_utils.h"
      32                 :            : #include "theory/datatypes/datatypes_rewriter.h"
      33                 :            : #include "theory/strings/word.h"
      34                 :            : #include "theory/uf/function_const.h"
      35                 :            : #include "theory/uf/theory_uf_rewriter.h"
      36                 :            : #include "util/bitvector.h"
      37                 :            : #include "util/finite_field_value.h"
      38                 :            : #include "util/floatingpoint.h"
      39                 :            : #include "util/iand.h"
      40                 :            : #include "util/rational.h"
      41                 :            : #include "util/regexp.h"
      42                 :            : #include "util/string.h"
      43                 :            : 
      44                 :            : using namespace cvc5::internal::kind;
      45                 :            : 
      46                 :            : namespace cvc5::internal {
      47                 :            : namespace proof {
      48                 :            : 
      49                 :       1417 : LfscNodeConverter::LfscNodeConverter(NodeManager* nm) : NodeConverter(nm)
      50                 :            : {
      51                 :       1417 :   d_arrow = nm->mkSortConstructor("arrow", 2);
      52                 :            : 
      53                 :       1417 :   d_sortType = nm->mkSort("sortType");
      54                 :            :   // the embedding of arrow into Node, which is binary constructor over sorts
      55                 :       7085 :   TypeNode anfType = nm->mkFunctionType({d_sortType, d_sortType}, d_sortType);
      56                 :       1417 :   d_typeAsNode[d_arrow] =
      57                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, anfType, "arrow");
      58                 :            : 
      59                 :       2834 :   TypeNode intType = nm->integerType();
      60                 :       7085 :   TypeNode arrType = nm->mkFunctionType({d_sortType, d_sortType}, d_sortType);
      61                 :       1417 :   d_typeKindToNodeCons[Kind::ARRAY_TYPE] =
      62                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, arrType, "Array");
      63                 :       2834 :   TypeNode bvType = nm->mkFunctionType(intType, d_sortType);
      64                 :       1417 :   d_typeKindToNodeCons[Kind::BITVECTOR_TYPE] =
      65                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, bvType, "BitVec");
      66                 :       7085 :   TypeNode fpType = nm->mkFunctionType({intType, intType}, d_sortType);
      67                 :       1417 :   d_typeKindToNodeCons[Kind::FLOATINGPOINT_TYPE] =
      68                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, fpType, "FloatingPoint");
      69                 :       1417 :   TypeNode setType = nm->mkFunctionType(d_sortType, d_sortType);
      70                 :       1417 :   d_typeKindToNodeCons[Kind::SET_TYPE] =
      71                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, setType, "Set");
      72                 :       1417 :   d_typeKindToNodeCons[Kind::BAG_TYPE] =
      73                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, setType, "Bag");
      74                 :       1417 :   d_typeKindToNodeCons[Kind::SEQUENCE_TYPE] =
      75                 :       2834 :       getSymbolInternal(Kind::FUNCTION_TYPE, setType, "Seq");
      76                 :       1417 : }
      77                 :            : 
      78                 :    2193070 : Node LfscNodeConverter::preConvert(Node n)
      79                 :            : {
      80                 :            :   // match is not supported in LFSC syntax, we eliminate it at pre-order
      81                 :            :   // traversal, which avoids type-checking errors during conversion, since e.g.
      82                 :            :   // match case nodes are required but cannot be preserved
      83         [ +  + ]:    2193070 :   if (n.getKind() == Kind::MATCH)
      84                 :            :   {
      85                 :          2 :     return theory::datatypes::DatatypesRewriter::expandMatch(n);
      86                 :            :   }
      87                 :    2193070 :   return n;
      88                 :            : }
      89                 :            : 
      90                 :    2186060 : Node LfscNodeConverter::postConvert(Node n)
      91                 :            : {
      92                 :    2186060 :   Kind k = n.getKind();
      93                 :            :   // we eliminate MATCH at preConvert above
      94 [ -  + ][ -  + ]:    2186060 :   Assert(k != Kind::MATCH);
                 [ -  - ]
      95         [ +  + ]:    2186060 :   if (k == Kind::ASCRIPTION_TYPE)
      96                 :            :   {
      97                 :            :     // dummy node, return it
      98                 :         11 :     return n;
      99                 :            :   }
     100                 :    4372110 :   TypeNode tn = n.getType();
     101         [ +  - ]:    4372110 :   Trace("lfsc-term-process-debug")
     102                 :    2186050 :       << "postConvert " << n << " " << k << std::endl;
     103         [ +  + ]:    2186050 :   if (k == Kind::BOUND_VARIABLE)
     104                 :            :   {
     105         [ -  + ]:       7790 :     if (d_symbols.find(n) != d_symbols.end())
     106                 :            :     {
     107                 :            :       // ignore internally generated symbols
     108                 :          0 :       return n;
     109                 :            :     }
     110                 :            :     // bound variable v is (bvar x T)
     111                 :      15580 :     TypeNode intType = d_nm->integerType();
     112                 :      23370 :     Node x = d_nm->mkConstInt(Rational(getOrAssignIndexForBVar(n)));
     113                 :      23370 :     Node tc = typeAsNode(convertType(tn));
     114                 :      38950 :     TypeNode ftype = d_nm->mkFunctionType({intType, d_sortType}, tn);
     115                 :      15580 :     Node bvarOp = getSymbolInternal(k, ftype, "bvar");
     116 [ +  + ][ -  - ]:      23370 :     return mkApplyUf(bvarOp, {x, tc});
     117                 :            :   }
     118         [ +  + ]:    2178260 :   else if (k == Kind::RAW_SYMBOL)
     119                 :            :   {
     120                 :            :     // ignore internally generated symbols
     121                 :      10293 :     return n;
     122                 :            :   }
     123 [ +  + ][ +  + ]:    2167970 :   else if (k == Kind::SKOLEM || k == Kind::DUMMY_SKOLEM)
     124                 :            :   {
     125                 :            :     // constructors/selectors are represented by skolems, which are defined
     126                 :            :     // symbols
     127         [ +  + ]:      10139 :     if (tn.isDatatypeConstructor() || tn.isDatatypeSelector()
     128 [ +  + ][ +  + ]:      10139 :         || tn.isDatatypeTester() || tn.isDatatypeUpdater())
         [ +  + ][ +  + ]
     129                 :            :     {
     130                 :            :       // note these are not converted to their user named (cvc.) symbols here,
     131                 :            :       // to avoid type errors when constructing terms for postConvert
     132                 :        746 :       return n;
     133                 :            :     }
     134                 :            :     // skolems v print as their original forms
     135                 :            :     // v is (skolem W) where W is the original or original form of v
     136                 :       8972 :     Node wi = SkolemManager::getUnpurifiedForm(n);
     137 [ +  - ][ +  + ]:       4486 :     if (!wi.isNull() && wi != n)
                 [ +  + ]
     138                 :            :     {
     139         [ +  - ]:       7286 :       Trace("lfsc-term-process-debug")
     140                 :       3643 :           << "...original form " << wi << std::endl;
     141                 :       3643 :       wi = convert(wi);
     142         [ +  - ]:       7286 :       Trace("lfsc-term-process-debug")
     143                 :       3643 :           << "...converted original for " << wi << std::endl;
     144                 :       7286 :       TypeNode ftype = d_nm->mkFunctionType(tn, tn);
     145                 :       7286 :       Node skolemOp = getSymbolInternal(k, ftype, "skolem");
     146                 :       7286 :       return mkApplyUf(skolemOp, {wi});
     147                 :            :     }
     148                 :            :     // might be a skolem function
     149                 :       1686 :     Node ns = maybeMkSkolemFun(n);
     150         [ +  + ]:        843 :     if (!ns.isNull())
     151                 :            :     {
     152                 :         85 :       return ns;
     153                 :            :     }
     154                 :            :     // Otherwise, it is an uncategorized skolem, must use a fresh variable.
     155                 :            :     // This case will only apply for terms originating from places with no
     156                 :            :     // proof support. Note it is not added as a declared variable, instead it
     157                 :            :     // is used as (var N T) throughout.
     158                 :       1516 :     TypeNode intType = d_nm->integerType();
     159                 :       3790 :     TypeNode varType = d_nm->mkFunctionType({intType, d_sortType}, tn);
     160                 :       2274 :     Node var = mkInternalSymbol("var", varType);
     161                 :       2274 :     Node index = d_nm->mkConstInt(Rational(getOrAssignIndexForFVar(n)));
     162                 :       1516 :     Node tc = typeAsNode(convertType(tn));
     163 [ +  + ][ -  - ]:       2274 :     return mkApplyUf(var, {index, tc});
     164                 :            :   }
     165         [ +  + ]:    2162740 :   else if (n.isVar())
     166                 :            :   {
     167                 :      15467 :     d_declVars.insert(n);
     168                 :      30934 :     return mkInternalSymbol(getNameForUserNameOf(n), tn);
     169                 :            :   }
     170         [ +  + ]:    2147270 :   else if (k == Kind::CARDINALITY_CONSTRAINT)
     171                 :            :   {
     172         [ +  - ]:         16 :     Trace("lfsc-term-process-debug")
     173                 :          8 :         << "...convert cardinality constraint" << std::endl;
     174                 :            :     const CardinalityConstraint& cc =
     175                 :          8 :         n.getOperator().getConst<CardinalityConstraint>();
     176                 :         24 :     Node tnn = typeAsNode(convertType(cc.getType()));
     177                 :         16 :     Node ub = d_nm->mkConstInt(Rational(cc.getUpperBound()));
     178                 :          8 :     TypeNode tnc = d_nm->mkFunctionType({tnn.getType(), ub.getType()},
     179                 :         48 :                                         d_nm->booleanType());
     180                 :         16 :     Node fcard = getSymbolInternal(k, tnc, "fmf.card");
     181 [ +  + ][ -  - ]:         24 :     return mkApplyUf(fcard, {tnn, ub});
     182                 :            :   }
     183         [ +  + ]:    2147260 :   else if (k == Kind::APPLY_UF)
     184                 :            :   {
     185                 :      69554 :     return convert(theory::uf::TheoryUfRewriter::getHoApplyForApplyUf(n));
     186                 :            :   }
     187 [ +  + ][ +  + ]:    2112490 :   else if (k == Kind::APPLY_CONSTRUCTOR || k == Kind::APPLY_SELECTOR
     188 [ +  + ][ +  + ]:    2109400 :            || k == Kind::APPLY_TESTER || k == Kind::APPLY_UPDATER)
     189                 :            :   {
     190                 :            :     // must add to declared types
     191                 :       3598 :     const DType& dt = DType::datatypeOf(n.getOperator());
     192                 :       3598 :     d_declTypes.insert(dt.getTypeNode());
     193                 :            :     // must convert other kinds of apply to functions, since we convert to
     194                 :            :     // HO_APPLY
     195                 :       7196 :     Node opc = getOperatorOfTerm(n, true);
     196         [ +  + ]:       3598 :     if (n.getNumChildren() == 0)
     197                 :            :     {
     198                 :         97 :       return opc;
     199                 :            :     }
     200                 :       7002 :     return postConvert(mkApplyUf(opc, std::vector<Node>(n.begin(), n.end())));
     201                 :            :   }
     202         [ +  + ]:    2108890 :   else if (k == Kind::HO_APPLY)
     203                 :            :   {
     204                 :    1158760 :     std::vector<TypeNode> argTypes;
     205                 :     579378 :     argTypes.push_back(n[0].getType());
     206                 :     579378 :     argTypes.push_back(n[1].getType());
     207                 :    1158760 :     TypeNode tnh = d_nm->mkFunctionType(argTypes, tn);
     208                 :    1158760 :     Node hconstf = getSymbolInternal(k, tnh, "apply");
     209 [ +  + ][ -  - ]:    1738130 :     return mkApplyUf(hconstf, {n[0], n[1]});
     210                 :            :   }
     211 [ +  + ][ +  + ]:    1529510 :   else if (k == Kind::CONST_RATIONAL || k == Kind::CONST_INTEGER)
     212                 :            :   {
     213                 :      37986 :     TypeNode tnv = d_nm->mkFunctionType(tn, tn);
     214                 :      37986 :     Node rconstf;
     215                 :      37986 :     Node arg;
     216                 :      18993 :     Rational r = n.getConst<Rational>();
     217         [ +  + ]:      18993 :     if (tn.isInteger())
     218                 :            :     {
     219                 :      15441 :       rconstf = getSymbolInternal(k, tnv, "int");
     220         [ +  + ]:      15441 :       if (r.sgn() == -1)
     221                 :            :       {
     222                 :            :         // use LFSC syntax for mpz negation
     223                 :       3346 :         Node mpzn = getSymbolInternal(k, d_nm->mkFunctionType(tn, tn), "~");
     224                 :       3346 :         arg = mkApplyUf(mpzn, {d_nm->mkConstInt(r.abs())});
     225                 :            :       }
     226                 :            :       else
     227                 :            :       {
     228                 :      13768 :         arg = n;
     229                 :            :       }
     230                 :            :     }
     231                 :            :     else
     232                 :            :     {
     233                 :       3552 :       rconstf = getSymbolInternal(k, tnv, "real");
     234                 :            :       // ensure rationals are printed properly here using mpq syntax
     235                 :            :       // Note that inconvieniently, LFSC uses (non-sexpr) syntax n/m for
     236                 :            :       // constant rationals, hence we must use a string
     237                 :       7104 :       std::stringstream ss;
     238                 :       3552 :       ss << "__LFSC_TMP" << r.getNumerator().abs() << "/" << r.getDenominator();
     239                 :       3552 :       arg = mkInternalSymbol(ss.str(), tn);
     240                 :            :       // negative (~ n/m)
     241         [ +  + ]:       3552 :       if (r.sgn() == -1)
     242                 :            :       {
     243                 :       3366 :         Node mpzn = getSymbolInternal(k, d_nm->mkFunctionType(tn, tn), "~");
     244                 :       3366 :         arg = mkApplyUf(mpzn, {arg});
     245                 :            :       }
     246                 :            :     }
     247                 :      37986 :     return mkApplyUf(rconstf, {arg});
     248                 :            :   }
     249         [ +  + ]:    1510520 :   else if (k == Kind::CONST_BITVECTOR)
     250                 :            :   {
     251                 :       2274 :     TypeNode btn = d_nm->booleanType();
     252                 :       2274 :     TypeNode tnv = d_nm->mkFunctionType(btn, tn);
     253                 :       2274 :     BitVector bv = n.getConst<BitVector>();
     254                 :       2274 :     Node ret = convertBitVector(bv);
     255                 :       2274 :     Node bconstf = getSymbolInternal(k, tnv, "bv");
     256                 :       2274 :     return mkApplyUf(bconstf, {ret});
     257                 :            :   }
     258         [ +  + ]:    1509380 :   else if (k == Kind::CONST_FLOATINGPOINT)
     259                 :            :   {
     260                 :         38 :     BitVector s, e, i;
     261                 :         19 :     n.getConst<FloatingPoint>().getIEEEBitvectors(s, e, i);
     262                 :         38 :     Node sn = convert(d_nm->mkConst(s));
     263                 :         38 :     Node en = convert(d_nm->mkConst(e));
     264                 :         38 :     Node in = convert(d_nm->mkConst(i));
     265                 :            :     TypeNode tnv =
     266                 :        114 :         d_nm->mkFunctionType({sn.getType(), en.getType(), in.getType()}, tn);
     267                 :         38 :     Node bconstf = getSymbolInternal(k, tnv, "fp");
     268 [ +  + ][ -  - ]:         76 :     return mkApplyUf(bconstf, {sn, en, in});
     269                 :            :   }
     270         [ +  + ]:    1509360 :   else if (k == Kind::CONST_FINITE_FIELD)
     271                 :            :   {
     272                 :         81 :     const FiniteFieldValue& ffv = n.getConst<FiniteFieldValue>();
     273                 :        243 :     Node v = convert(d_nm->mkConstInt(ffv.getValue()));
     274                 :        243 :     Node fs = convert(d_nm->mkConstInt(ffv.getFieldSize()));
     275                 :        405 :     TypeNode tnv = d_nm->mkFunctionType({v.getType(), fs.getType()}, tn);
     276                 :        162 :     Node ffconstf = getSymbolInternal(k, tnv, "ff.value");
     277 [ +  + ][ -  - ]:        243 :     return mkApplyUf(ffconstf, {v, fs});
     278                 :            :   }
     279         [ +  + ]:    1509280 :   else if (k == Kind::CONST_STRING)
     280                 :            :   {
     281                 :            :     //"" is emptystr
     282                 :            :     //"A" is (char 65)
     283                 :            :     //"ABC" is (str.++ (char 65) (str.++ (char 66) (str.++ (char 67) emptystr)))
     284                 :       1940 :     std::vector<Node> charVec;
     285                 :        970 :     getCharVectorInternal(n, charVec);
     286 [ -  + ][ -  + ]:        970 :     Assert(!charVec.empty());
                 [ -  - ]
     287         [ +  + ]:        970 :     if (charVec.size() == 1)
     288                 :            :     {
     289                 :            :       // handles empty string and singleton character
     290                 :        701 :       return charVec[0];
     291                 :            :     }
     292                 :        269 :     std::reverse(charVec.begin(), charVec.end());
     293                 :        807 :     Node ret = postConvert(getNullTerminator(Kind::STRING_CONCAT, tn));
     294         [ +  + ]:       2891 :     for (size_t i = 0, size = charVec.size(); i < size; i++)
     295                 :            :     {
     296                 :       2622 :       ret = d_nm->mkNode(Kind::STRING_CONCAT, charVec[i], ret);
     297                 :            :     }
     298                 :        269 :     return ret;
     299                 :            :   }
     300         [ +  + ]:    1508310 :   else if (k == Kind::CONST_SEQUENCE)
     301                 :            :   {
     302                 :         53 :     const std::vector<Node>& charVec = n.getConst<Sequence>().getVec();
     303                 :        106 :     TypeNode etype = d_nm->mkFunctionType(d_sortType, tn);
     304                 :        159 :     Node ret = getSymbolInternal(k, etype, "seq.empty");
     305                 :        106 :     ret = mkApplyUf(ret, {typeAsNode(convertType(tn))});
     306                 :        106 :     std::vector<Node> vecu;
     307         [ +  + ]:         83 :     for (size_t i = 0, size = charVec.size(); i < size; i++)
     308                 :            :     {
     309                 :            :       Node u =
     310                 :        106 :           d_nm->mkNode(Kind::SEQ_UNIT, postConvert(charVec[size - (i + 1)]));
     311         [ +  + ]:         53 :       if (size == 1)
     312                 :            :       {
     313                 :            :         // singleton case
     314                 :         23 :         return u;
     315                 :            :       }
     316                 :         30 :       ret = d_nm->mkNode(Kind::STRING_CONCAT, u, ret);
     317                 :            :     }
     318                 :         30 :     return ret;
     319                 :            :   }
     320         [ +  + ]:    1508260 :   else if (k == Kind::STORE_ALL)
     321                 :            :   {
     322                 :         57 :     Node t = typeAsNode(convertType(tn));
     323                 :         38 :     TypeNode caRetType = d_nm->mkFunctionType(tn.getArrayConstituentType(), tn);
     324                 :         38 :     TypeNode catype = d_nm->mkFunctionType(d_sortType, caRetType);
     325                 :         57 :     Node bconstf = getSymbolInternal(k, catype, "array_const");
     326                 :         76 :     Node f = mkApplyUf(bconstf, {t});
     327                 :         19 :     ArrayStoreAll storeAll = n.getConst<ArrayStoreAll>();
     328                 :         38 :     return mkApplyUf(f, {convert(storeAll.getValue())});
     329                 :            :   }
     330 [ +  + ][ +  + ]:    1487430 :   else if (k == Kind::GEQ || k == Kind::GT || k == Kind::LEQ || k == Kind::LT
                 [ +  + ]
     331 [ +  + ][ +  + ]:    1453230 :            || k == Kind::SUB || k == Kind::DIVISION || k == Kind::DIVISION_TOTAL
                 [ +  + ]
     332 [ +  + ][ +  + ]:    1451070 :            || k == Kind::INTS_DIVISION || k == Kind::INTS_DIVISION_TOTAL
     333 [ +  + ][ +  + ]:    1450660 :            || k == Kind::INTS_MODULUS || k == Kind::INTS_MODULUS_TOTAL
     334 [ +  + ][ +  + ]:    1450390 :            || k == Kind::NEG || k == Kind::POW
     335         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_NAN
     336         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_INF
     337         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_ZERO
     338         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_SIGN
     339         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_EXPONENT
     340         [ +  + ]:    1449860 :            || k == Kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND
     341         [ +  - ]:    1449850 :            || k == Kind::ROUNDINGMODE_BITBLAST
     342 [ +  + ][ +  + ]:    2995670 :            || GenericOp::isIndexedOperatorKind(k))
                 [ +  + ]
     343                 :            :   {
     344                 :            :     // must give special names to SMT-LIB operators with arithmetic subtyping
     345                 :            :     // note that SUB is not n-ary
     346                 :            :     // get the macro-apply version of the operator
     347                 :      67830 :     Node opc = getOperatorOfTerm(n, true);
     348                 :      67830 :     return mkApplyUf(opc, std::vector<Node>(n.begin(), n.end()));
     349                 :            :   }
     350 [ +  + ][ +  + ]:    1440410 :   else if (k == Kind::SET_EMPTY || k == Kind::SET_UNIVERSE
     351         [ +  + ]:    1440340 :            || k == Kind::BAG_EMPTY)
     352                 :            :   {
     353                 :        225 :     Node t = typeAsNode(convertType(tn));
     354                 :        150 :     TypeNode etype = d_nm->mkFunctionType(d_sortType, tn);
     355                 :            :     Node ef = getSymbolInternal(
     356                 :            :         k,
     357                 :            :         etype,
     358                 :         75 :         k == Kind::SET_EMPTY
     359                 :            :             ? "set.empty"
     360 [ +  + ][ +  + ]:        150 :             : (k == Kind::SET_UNIVERSE ? "set.universe" : "bag.empty"));
     361                 :        150 :     return mkApplyUf(ef, {t});
     362                 :            :   }
     363         [ +  + ]:    1440330 :   else if (n.isClosure())
     364                 :            :   {
     365                 :            :     // (forall ((x1 T1) ... (xn Tk)) P) is
     366                 :            :     // ((forall x1 T1) ((forall x2 T2) ... ((forall xk Tk) P))). We use
     367                 :            :     // SEXPR to do this, which avoids the need for indexed operators.
     368                 :      31858 :     Node ret = n[1];
     369                 :      31858 :     Node cop = getOperatorOfClosure(n, true);
     370                 :      31858 :     Node pcop = getOperatorOfClosure(n, true, true);
     371         [ +  + ]:      58599 :     for (size_t i = 0, nchild = n[0].getNumChildren(); i < nchild; i++)
     372                 :            :     {
     373                 :      42670 :       size_t ii = (nchild - 1) - i;
     374                 :      85340 :       Node v = n[0][ii];
     375                 :            :       // use the partial operator for variables except the last one.  This
     376                 :            :       // avoids type errors in internal representation of LFSC terms.
     377         [ +  + ]:      85340 :       Node vop = getOperatorOfBoundVar(ii == 0 ? cop : pcop, v);
     378                 :      85340 :       ret = mkApplyUf(vop, {ret});
     379                 :            :     }
     380                 :            :     // notice that intentionally we drop annotations here
     381                 :      15929 :     return ret;
     382                 :            :   }
     383         [ +  + ]:    1424400 :   else if (k == Kind::FUNCTION_ARRAY_CONST)
     384                 :            :   {
     385                 :            :     // must convert to lambda and then run the conversion
     386                 :         18 :     Node lam = theory::uf::FunctionConst::toLambda(n);
     387 [ -  + ][ -  + ]:         18 :     Assert(!lam.isNull());
                 [ -  - ]
     388                 :         18 :     return convert(lam);
     389                 :            :   }
     390         [ -  + ]:    1424390 :   else if (k == Kind::REGEXP_LOOP)
     391                 :            :   {
     392                 :            :     // ((_ re.loop n1 n2) t) is ((re.loop n1 n2) t)
     393                 :          0 :     TypeNode intType = d_nm->integerType();
     394                 :            :     TypeNode relType =
     395                 :          0 :         d_nm->mkFunctionType({intType, intType}, d_nm->mkFunctionType(tn, tn));
     396                 :            :     Node rop = getSymbolInternal(
     397                 :          0 :         k, relType, printer::smt2::Smt2Printer::smtKindString(k));
     398                 :          0 :     RegExpLoop op = n.getOperator().getConst<RegExpLoop>();
     399                 :          0 :     Node n1 = d_nm->mkConstInt(Rational(op.d_loopMinOcc));
     400                 :          0 :     Node n2 = d_nm->mkConstInt(Rational(op.d_loopMaxOcc));
     401                 :          0 :     return mkApplyUf(mkApplyUf(rop, {n1, n2}), {n[0]});
     402                 :            :   }
     403         [ +  + ]:    1424390 :   else if (k == Kind::BITVECTOR_FROM_BOOLS)
     404                 :            :   {
     405                 :       5130 :     TypeNode btn = d_nm->booleanType();
     406                 :            :     // (from_bools t1 ... tn) is
     407                 :            :     // (from_bools t1 (from_bools t2 ... (from_bools tn emptybv)))
     408                 :            :     // where notice that each from_bools has a different type
     409                 :       5130 :     Node curr = getNullTerminator(Kind::BITVECTOR_CONCAT, tn);
     410         [ +  + ]:      17412 :     for (size_t i = 0, nchild = n.getNumChildren(); i < nchild; ++i)
     411                 :            :     {
     412                 :      29694 :       TypeNode bvt = d_nm->mkBitVectorType(i + 1);
     413                 :      74235 :       TypeNode ftype = d_nm->mkFunctionType({btn, curr.getType()}, bvt);
     414                 :      29694 :       Node bbt = getSymbolInternal(k, ftype, "from_bools");
     415 [ +  + ][ -  - ]:      44541 :       curr = mkApplyUf(bbt, {n[nchild - (i + 1)], curr});
     416                 :            :     }
     417                 :       2565 :     return curr;
     418                 :            :   }
     419         [ +  + ]:    1421820 :   else if (k == Kind::SEP_NIL)
     420                 :            :   {
     421                 :          9 :     Node tnn = typeAsNode(convertType(tn));
     422                 :          6 :     TypeNode ftype = d_nm->mkFunctionType(d_sortType, tn);
     423                 :          6 :     Node s = getSymbolInternal(k, ftype, "sep.nil");
     424                 :          6 :     return mkApplyUf(s, {tnn});
     425                 :            :   }
     426 [ +  + ][ +  + ]:    1421820 :   else if (NodeManager::isNAryKind(k) && n.getNumChildren() >= 2)
                 [ +  + ]
     427                 :            :   {
     428                 :     436970 :     size_t nchild = n.getNumChildren();
     429 [ -  + ][ -  + ]:     436970 :     Assert(n.getMetaKind() != metakind::PARAMETERIZED);
                 [ -  - ]
     430                 :            :     // convert all n-ary applications to binary
     431                 :     873940 :     std::vector<Node> children(n.begin(), n.end());
     432                 :            :     // distinct is special case
     433         [ +  + ]:     436970 :     if (k == Kind::DISTINCT)
     434                 :            :     {
     435                 :            :       // DISTINCT(x1,...,xn) --->
     436                 :            :       // AND(DISTINCT(x1,x2), AND(,..., AND(,..,DISTINCT(x_{n-1},x_n))))
     437                 :       4269 :       Node ret = d_nm->mkNode(k, children[0], children[1]);
     438         [ +  + ]:       4729 :       for (unsigned i = 0; i < nchild; i++)
     439         [ +  + ]:      15518 :         for (unsigned j = i + 1; j < nchild; j++)
     440                 :            :         {
     441 [ +  + ][ +  - ]:      12212 :           if (i != 0 && j != 1)
     442                 :            :           {
     443                 :      20658 :             ret = d_nm->mkNode(
     444                 :      30987 :                 Kind::AND, ret, d_nm->mkNode(k, children[i], children[j]));
     445                 :            :           }
     446                 :            :         }
     447         [ +  - ]:       2846 :       Trace("lfsc-term-process-debug") << "n: " << n << std::endl
     448                 :       1423 :                                        << "ret: " << ret << std::endl;
     449                 :       1423 :       return ret;
     450                 :            :     }
     451                 :     435547 :     std::reverse(children.begin(), children.end());
     452                 :            :     // Add the null-terminator. This is done to disambiguate the number
     453                 :            :     // of children for term with n-ary operators. In particular note that
     454                 :            :     // (or A B C (or D E)) has representation:
     455                 :            :     //   (or A (or B (or C (or (or D E) false))))
     456                 :            :     // This makes the AST above distinguishable from (or A B C D E),
     457                 :            :     // which otherwise would both have representation:
     458                 :            :     //   (or A (or B (or C (or D E))))
     459                 :     871094 :     Node nullTerm = getNullTerminator(k, tn);
     460                 :            :     // Most operators simply get binarized
     461                 :     871094 :     Node ret;
     462                 :     435547 :     size_t istart = 0;
     463         [ +  + ]:     435547 :     if (nullTerm.isNull())
     464                 :            :     {
     465                 :         61 :       ret = children[0];
     466                 :         61 :       istart = 1;
     467                 :            :     }
     468                 :            :     else
     469                 :            :     {
     470                 :            :       // must convert recursively, since nullTerm may have subterms.
     471                 :     435486 :       ret = convert(nullTerm);
     472                 :            :     }
     473                 :            :     // check whether we are also changing the operator name, in which case
     474                 :            :     // we build a binary uninterpreted function opc
     475                 :     435547 :     bool isArithOp =
     476 [ +  + ][ +  + ]:     435547 :         (k == Kind::ADD || k == Kind::MULT || k == Kind::NONLINEAR_MULT);
                 [ +  + ]
     477                 :     871094 :     std::stringstream arithOpName;
     478         [ +  + ]:     435547 :     if (isArithOp)
     479                 :            :     {
     480                 :            :       // currently allow subtyping
     481                 :      81553 :       arithOpName << "a.";
     482                 :      81553 :       arithOpName << printer::smt2::Smt2Printer::smtKindString(k);
     483                 :            :     }
     484                 :            :     // now, iterate over children and make binary conversion
     485         [ +  + ]:    2286580 :     for (size_t i = istart, npchild = children.size(); i < npchild; i++)
     486                 :            :     {
     487         [ +  + ]:    1851030 :       if (isArithOp)
     488                 :            :       {
     489                 :            :         // Arithmetic operators must deal with permissive type rules for
     490                 :            :         // ADD, MULT, NONLINEAR_MULT. We use the properly typed operator to
     491                 :            :         // avoid debug failures.
     492                 :     467774 :         TypeNode tn1 = children[i].getType();
     493                 :     467774 :         TypeNode tn2 = ret.getType();
     494                 :    1169440 :         TypeNode ftype = d_nm->mkFunctionType({tn1, tn2}, tn);
     495                 :     467774 :         Node opc = getSymbolInternal(k, ftype, arithOpName.str());
     496 [ +  + ][ -  - ]:     701661 :         ret = mkApplyUf(opc, {children[i], ret});
     497                 :            :       }
     498                 :            :       else
     499                 :            :       {
     500                 :    1617150 :         ret = d_nm->mkNode(k, children[i], ret);
     501                 :            :       }
     502                 :            :     }
     503         [ +  - ]:     871094 :     Trace("lfsc-term-process-debug")
     504                 :     435547 :         << "...return n-ary conv " << ret << std::endl;
     505                 :     435547 :     return ret;
     506                 :            :   }
     507                 :     984849 :   return n;
     508                 :            : }
     509                 :            : 
     510                 :    1064200 : Node LfscNodeConverter::mkApplyUf(Node op, const std::vector<Node>& args) const
     511                 :            : {
     512                 :    2128390 :   std::vector<Node> aargs;
     513         [ +  + ]:    1064200 :   if (op.isVar())
     514                 :            :   {
     515                 :    1011560 :     aargs.push_back(op);
     516                 :            :   }
     517                 :            :   else
     518                 :            :   {
     519                 :            :     // Note that dag threshold is disabled for printing operators.
     520                 :     105282 :     std::stringstream ss;
     521                 :      52641 :     options::ioutils::applyOutputLanguage(ss, Language::LANG_SMTLIB_V2_6);
     522                 :      52641 :     options::ioutils::applyDagThresh(ss, 0);
     523                 :      52641 :     ss << op;
     524                 :     157923 :     Node opv = d_nm->mkRawSymbol(ss.str(), op.getType());
     525                 :      52641 :     aargs.push_back(opv);
     526                 :            :   }
     527                 :    1064200 :   aargs.insert(aargs.end(), args.begin(), args.end());
     528                 :    2128390 :   return d_nm->mkNode(Kind::APPLY_UF, aargs);
     529                 :            : }
     530                 :            : 
     531                 :       6053 : TypeNode LfscNodeConverter::preConvertType(TypeNode tn)
     532                 :            : {
     533         [ +  + ]:       6053 :   if (tn.getKind() == Kind::TUPLE_TYPE)
     534                 :            :   {
     535                 :            :     // Must collect the tuple type here, since at post-order traversal, the
     536                 :            :     // type has been modified and no longer maintains the mapping to its
     537                 :            :     // datatype encoding.
     538                 :         80 :     d_declTypes.insert(tn);
     539                 :            :   }
     540                 :       6053 :   return tn;
     541                 :            : }
     542                 :            : 
     543                 :       6053 : TypeNode LfscNodeConverter::postConvertType(TypeNode tn)
     544                 :            : {
     545                 :       6053 :   TypeNode cur = tn;
     546                 :      12106 :   Node tnn;
     547                 :       6053 :   Kind k = tn.getKind();
     548         [ +  - ]:      12106 :   Trace("lfsc-term-process-debug")
     549                 :       6053 :       << "postConvertType " << tn << " " << tn.getNumChildren() << " " << k
     550                 :       6053 :       << std::endl;
     551         [ +  + ]:       6053 :   if (k == Kind::FUNCTION_TYPE)
     552                 :            :   {
     553                 :            :     // (-> T1 ... Tn T) is (arrow T1 .... (arrow Tn T))
     554                 :       4948 :     std::vector<TypeNode> argTypes = tn.getArgTypes();
     555                 :            :     // also make the node embedding of the type
     556                 :       4948 :     Node arrown = d_typeAsNode[d_arrow];
     557 [ -  + ][ -  + ]:       2474 :     Assert(!arrown.isNull());
                 [ -  - ]
     558                 :       2474 :     cur = tn.getRangeType();
     559                 :       2474 :     tnn = typeAsNode(cur);
     560                 :       7145 :     for (std::vector<TypeNode>::reverse_iterator it = argTypes.rbegin();
     561         [ +  + ]:       7145 :          it != argTypes.rend();
     562                 :       4671 :          ++it)
     563                 :            :     {
     564                 :       4671 :       std::vector<TypeNode> aargs;
     565                 :       4671 :       aargs.push_back(*it);
     566                 :       4671 :       aargs.push_back(cur);
     567                 :       4671 :       cur = d_nm->mkSort(d_arrow, aargs);
     568 [ +  + ][ -  - ]:      14013 :       tnn = mkApplyUf(arrown, {typeAsNode(*it), tnn});
     569                 :            :     }
     570                 :            :   }
     571         [ +  + ]:       3579 :   else if (k == Kind::BITVECTOR_TYPE)
     572                 :            :   {
     573                 :        473 :     tnn = d_typeKindToNodeCons[k];
     574                 :        473 :     Node w = d_nm->mkConstInt(Rational(tn.getBitVectorSize()));
     575                 :        946 :     tnn = mkApplyUf(tnn, {w});
     576                 :            :   }
     577         [ +  + ]:       3106 :   else if (k == Kind::FLOATINGPOINT_TYPE)
     578                 :            :   {
     579                 :          6 :     tnn = d_typeKindToNodeCons[k];
     580                 :         12 :     Node e = d_nm->mkConstInt(Rational(tn.getFloatingPointExponentSize()));
     581                 :          6 :     Node s = d_nm->mkConstInt(Rational(tn.getFloatingPointSignificandSize()));
     582 [ +  + ][ -  - ]:         18 :     tnn = mkApplyUf(tnn, {e, s});
     583                 :            :   }
     584         [ +  + ]:       3100 :   else if (k == Kind::TUPLE_TYPE)
     585                 :            :   {
     586                 :            :     // special case: tuples must be distinguished by their arity
     587                 :         80 :     size_t nargs = tn.getNumChildren();
     588         [ +  + ]:         80 :     if (nargs > 0)
     589                 :            :     {
     590                 :        158 :       std::vector<TypeNode> types;
     591                 :        158 :       std::vector<TypeNode> convTypes;
     592                 :        158 :       std::vector<Node> targs;
     593         [ +  + ]:        255 :       for (size_t i = 0; i < nargs; i++)
     594                 :            :       {
     595                 :        176 :         TypeNode tnc = tn[i];
     596                 :        176 :         types.push_back(d_sortType);
     597                 :        176 :         convTypes.push_back(tnc);
     598                 :        176 :         targs.push_back(typeAsNode(tnc));
     599                 :            :       }
     600                 :        158 :       TypeNode ftype = d_nm->mkFunctionType(types, d_sortType);
     601                 :            :       // must distinguish by arity
     602                 :         79 :       std::stringstream ss;
     603                 :         79 :       ss << "Tuple_" << nargs;
     604                 :         79 :       tnn = mkApplyUf(getSymbolInternal(k, ftype, ss.str()), targs);
     605                 :            :       // we are changing its name, we must make a sort constructor
     606                 :         79 :       cur = d_nm->mkSortConstructor(ss.str(), nargs);
     607                 :         79 :       cur = d_nm->mkSort(cur, convTypes);
     608                 :            :     }
     609                 :            :     else
     610                 :            :     {
     611                 :            :       // no need to convert type for tuples of size 0,
     612                 :            :       // type as node is simple
     613                 :          1 :       tnn = getSymbolInternal(k, d_sortType, "UnitTuple");
     614                 :            :     }
     615                 :            :   }
     616         [ +  + ]:       3020 :   else if (tn.getNumChildren() == 0)
     617                 :            :   {
     618 [ -  + ][ -  + ]:       2657 :     Assert(!tn.isTuple());
                 [ -  - ]
     619                 :            :     // an uninterpreted sort, or an uninstantiatied (maybe parametric) datatype
     620                 :       2657 :     d_declTypes.insert(tn);
     621                 :       5314 :     std::stringstream ss;
     622                 :       2657 :     options::ioutils::applyOutputLanguage(ss, Language::LANG_SMTLIB_V2_6);
     623                 :       2657 :     tn.toStream(ss);
     624         [ +  + ]:       2657 :     if (tn.isUninterpretedSortConstructor())
     625                 :            :     {
     626                 :         12 :       std::string s = getNameForUserNameOfInternal(tn.getId(), ss.str());
     627                 :         12 :       tnn = getSymbolInternal(k, d_sortType, s, false);
     628                 :            :       cur =
     629                 :         12 :           d_nm->mkSortConstructor(s, tn.getUninterpretedSortConstructorArity());
     630                 :            :     }
     631 [ +  + ][ +  + ]:       2645 :     else if (tn.isUninterpretedSort() || tn.isDatatype())
                 [ +  + ]
     632                 :            :     {
     633                 :       1396 :       std::string s = getNameForUserNameOfInternal(tn.getId(), ss.str());
     634                 :       1396 :       tnn = getSymbolInternal(k, d_sortType, s, false);
     635                 :       1396 :       cur = d_nm->mkSort(s);
     636                 :            :     }
     637                 :            :     else
     638                 :            :     {
     639                 :            :       // all other builtin type constants, e.g. Int
     640                 :       1249 :       tnn = getSymbolInternal(k, d_sortType, ss.str());
     641                 :            :     }
     642                 :            :   }
     643                 :            :   else
     644                 :            :   {
     645                 :            :     // to build the type-as-node, must convert the component types
     646                 :        726 :     std::vector<Node> targs;
     647                 :        726 :     std::vector<TypeNode> types;
     648         [ +  + ]:        880 :     for (const TypeNode& tnc : tn)
     649                 :            :     {
     650                 :        517 :       targs.push_back(typeAsNode(tnc));
     651                 :        517 :       types.push_back(d_sortType);
     652                 :            :     }
     653                 :        726 :     Node op;
     654         [ +  + ]:        363 :     if (k == Kind::PARAMETRIC_DATATYPE)
     655                 :            :     {
     656                 :            :       // note we don't add to declared types here, since the parametric
     657                 :            :       // datatype is traversed and will be declared as a type constructor
     658                 :            :       // erase first child, which repeats the datatype
     659                 :          8 :       targs.erase(targs.begin(), targs.begin() + 1);
     660                 :          8 :       types.erase(types.begin(), types.begin() + 1);
     661                 :         16 :       TypeNode ftype = d_nm->mkFunctionType(types, d_sortType);
     662                 :            :       // the operator has been converted; it is no longer a datatype, thus
     663                 :            :       // we must print to get its name.
     664                 :          8 :       std::stringstream ss;
     665                 :          8 :       ss << tn[0];
     666                 :          8 :       op = getSymbolInternal(k, ftype, ss.str());
     667                 :            :     }
     668         [ +  + ]:        355 :     else if (k == Kind::INSTANTIATED_SORT_TYPE)
     669                 :            :     {
     670                 :            :       // We don't add to declared types here. The type constructor is already
     671                 :            :       // added to declare types when processing the children of this.
     672                 :            :       // Also, similar to PARAMETRIC_DATATYPE, the type constructor
     673                 :            :       // should be erased from children.
     674                 :         40 :       targs.erase(targs.begin(), targs.begin() + 1);
     675                 :         40 :       types.erase(types.begin(), types.begin() + 1);
     676                 :         80 :       TypeNode ftype = d_nm->mkFunctionType(types, d_sortType);
     677                 :         40 :       std::string name = tn.getUninterpretedSortConstructor().getName();
     678                 :         40 :       op = getSymbolInternal(k, ftype, name, false);
     679                 :            :     }
     680         [ +  + ]:        315 :     else if (k == Kind::NULLABLE_TYPE)
     681                 :            :     {
     682                 :          2 :       TypeNode ftype = d_nm->mkFunctionType(d_sortType, d_sortType);
     683                 :          2 :       op = getSymbolInternal(k, ftype, "Nullable", false);
     684                 :            :     }
     685                 :            :     else
     686                 :            :     {
     687                 :        313 :       std::map<Kind, Node>::iterator it = d_typeKindToNodeCons.find(k);
     688         [ +  - ]:        313 :       if (it != d_typeKindToNodeCons.end())
     689                 :            :       {
     690                 :        313 :         op = it->second;
     691                 :            :       }
     692                 :            :     }
     693         [ +  - ]:        363 :     if (!op.isNull())
     694                 :            :     {
     695                 :        363 :       tnn = mkApplyUf(op, targs);
     696                 :            :     }
     697                 :            :     else
     698                 :            :     {
     699                 :          0 :       AlwaysAssert(false);
     700                 :            :     }
     701                 :            :   }
     702 [ -  + ][ -  + ]:       6053 :   Assert(!tnn.isNull());
                 [ -  - ]
     703         [ +  - ]:       6053 :   Trace("lfsc-term-process-debug") << "...type as node: " << tnn << std::endl;
     704                 :       6053 :   d_typeAsNode[cur] = tnn;
     705                 :      12106 :   return cur;
     706                 :            : }
     707                 :            : 
     708                 :      22633 : std::string LfscNodeConverter::getNameForUserName(const std::string& name,
     709                 :            :                                                   size_t variant)
     710                 :            : {
     711                 :            :   // For user name X, we do cvc.Y, where Y contains an escaped version of X.
     712                 :            :   // Specifically, since LFSC does not allow these characters in identifier
     713                 :            :   // bodies: "() \t\n\f;", each is replaced with an escape sequence "\xXX"
     714                 :            :   // where XX is the zero-padded hex representation of the code point. "\\" is
     715                 :            :   // also escaped.
     716                 :            :   //
     717                 :            :   // See also: https://github.com/cvc5/LFSC/blob/master/src/lexer.flex#L24
     718                 :            :   //
     719                 :            :   // The "cvc." prefix ensures we do not clash with LFSC definitions.
     720                 :            :   //
     721                 :            :   // The escaping ensures that all names are valid LFSC identifiers.
     722                 :      45266 :   std::stringstream ss;
     723                 :      22633 :   ss << "cvc";
     724         [ +  + ]:      22633 :   if (variant != 0)
     725                 :            :   {
     726                 :         11 :     ss << variant;
     727                 :            :   }
     728                 :      22633 :   ss << ".";
     729                 :      22633 :   std::string sanitized = ss.str();
     730                 :      22633 :   size_t found = sanitized.size();
     731                 :      22633 :   sanitized += name;
     732                 :            :   // The following sanitizes symbols that are not allowed in LFSC identifiers
     733                 :            :   // here, e.g.
     734                 :            :   //   |a b|
     735                 :            :   // is converted to:
     736                 :            :   //   cvc.a\x20b
     737                 :            :   // where "20" is the hex unicode value of " ".
     738                 :       1247 :   do
     739                 :            :   {
     740                 :      23880 :     found = sanitized.find_first_of("() \t\n\f\\;", found);
     741         [ +  + ]:      23880 :     if (found != std::string::npos)
     742                 :            :     {
     743                 :            :       // Emit hex sequence
     744                 :       1247 :       std::stringstream seq;
     745                 :       1247 :       seq << "\\x" << std::setbase(16) << std::setfill('0') << std::setw(2)
     746                 :       1247 :           << static_cast<size_t>(sanitized[found]);
     747                 :       1247 :       sanitized.replace(found, 1, seq.str());
     748                 :            :       // increment found over the escape
     749                 :       1247 :       found += 3;
     750                 :            :     }
     751         [ +  + ]:      23880 :   } while (found != std::string::npos);
     752                 :      45266 :   return sanitized;
     753                 :            : }
     754                 :            : 
     755                 :      21215 : std::string LfscNodeConverter::getNameForUserNameOf(Node v)
     756                 :            : {
     757                 :      42430 :   std::string name = v.getName();
     758                 :      42430 :   return getNameForUserNameOfInternal(v.getId(), name);
     759                 :            : }
     760                 :            : 
     761                 :      22623 : std::string LfscNodeConverter::getNameForUserNameOfInternal(
     762                 :            :     uint64_t id, const std::string& name)
     763                 :            : {
     764                 :      22623 :   std::vector<uint64_t>& syms = d_userSymbolList[name];
     765                 :      22623 :   size_t variant = 0;
     766                 :            :   std::vector<uint64_t>::iterator itr =
     767                 :      22623 :       std::find(syms.begin(), syms.end(), id);
     768         [ +  + ]:      22623 :   if (itr != syms.cend())
     769                 :            :   {
     770                 :       4520 :     variant = std::distance(syms.begin(), itr);
     771                 :            :   }
     772                 :            :   else
     773                 :            :   {
     774                 :      18103 :     variant = syms.size();
     775                 :      18103 :     syms.push_back(id);
     776                 :            :   }
     777                 :      45246 :   return getNameForUserName(name, variant);
     778                 :            : }
     779                 :            : 
     780                 :    2193070 : bool LfscNodeConverter::shouldTraverse(Node n)
     781                 :            : {
     782                 :    2193070 :   Kind k = n.getKind();
     783                 :            :   // don't convert bound variable or instantiation pattern list directly
     784 [ +  + ][ +  + ]:    2193070 :   if (k == Kind::BOUND_VAR_LIST || k == Kind::INST_PATTERN_LIST)
     785                 :            :   {
     786                 :       8503 :     return false;
     787                 :            :   }
     788                 :            :   // should not traverse internal applications
     789         [ +  + ]:    2184570 :   if (k == Kind::APPLY_UF)
     790                 :            :   {
     791         [ +  + ]:      33600 :     if (d_symbols.find(n.getOperator()) != d_symbols.end())
     792                 :            :     {
     793                 :       2324 :       return false;
     794                 :            :     }
     795                 :            :   }
     796                 :    2182240 :   return true;
     797                 :            : }
     798                 :            : 
     799                 :       2524 : Node LfscNodeConverter::maybeMkSkolemFun(Node k, bool macroApply)
     800                 :            : {
     801                 :       2524 :   SkolemManager* sm = d_nm->getSkolemManager();
     802                 :       2524 :   SkolemId sfi = SkolemId::NONE;
     803                 :       5048 :   Node cacheVal;
     804                 :       5048 :   TypeNode tn = k.getType();
     805         [ +  + ]:       2524 :   if (sm->isSkolemFunction(k, sfi, cacheVal))
     806                 :            :   {
     807         [ +  + ]:        641 :     if (sfi == SkolemId::RE_UNFOLD_POS_COMPONENT)
     808                 :            :     {
     809                 :            :       // a skolem corresponding to a regular expression unfolding component
     810                 :            :       // should print as (skolem_re_unfold_pos t R n) where the skolem is the
     811                 :            :       // n^th component for the unfolding of (str.in_re t R).
     812                 :        170 :       TypeNode strType = d_nm->stringType();
     813                 :        170 :       TypeNode reType = d_nm->regExpType();
     814                 :        170 :       TypeNode intType = d_nm->integerType();
     815                 :        510 :       TypeNode reut = d_nm->mkFunctionType({strType, reType, intType}, strType);
     816                 :        170 :       Node sk = getSymbolInternal(k.getKind(), reut, "skolem_re_unfold_pos");
     817 [ +  - ][ +  - ]:        170 :       Assert(!cacheVal.isNull() && cacheVal.getKind() == Kind::SEXPR
         [ +  - ][ -  + ]
                 [ -  - ]
     818                 :            :              && cacheVal.getNumChildren() == 3);
     819                 :            :       // third value is mpz, which is not converted
     820                 :            :       return mkApplyUf(sk,
     821 [ +  + ][ -  - ]:        340 :           {convert(cacheVal[0]), convert(cacheVal[1]), cacheVal[2]});
     822                 :            :     }
     823                 :            :   }
     824                 :       2439 :   return Node::null();
     825                 :            : }
     826                 :            : 
     827                 :      64440 : Node LfscNodeConverter::typeAsNode(TypeNode tni) const
     828                 :            : {
     829                 :            :   // should always exist in the cache, as we always run types through
     830                 :            :   // postConvertType before calling this method.
     831                 :      64440 :   std::map<TypeNode, Node>::const_iterator it = d_typeAsNode.find(tni);
     832 [ -  + ][ -  + ]:      64440 :   AlwaysAssert(it != d_typeAsNode.end()) << "Missing typeAsNode " << tni;
                 [ -  - ]
     833                 :     128880 :   return it->second;
     834                 :            : }
     835                 :            : 
     836                 :     431224 : Node LfscNodeConverter::mkInternalSymbol(const std::string& name,
     837                 :            :                                          TypeNode tn,
     838                 :            :                                          bool useRawSym)
     839                 :            : {
     840                 :            :   // use raw symbol so that it is never quoted
     841                 :            :   Node sym =
     842         [ +  + ]:     431224 :       useRawSym ? d_nm->mkRawSymbol(name, tn) : d_nm->mkBoundVar(name, tn);
     843                 :     431224 :   d_symbols.insert(sym);
     844                 :     431224 :   return sym;
     845                 :            : }
     846                 :            : 
     847                 :        407 : Node LfscNodeConverter::getSymbolInternalFor(Node n,
     848                 :            :                                              const std::string& name,
     849                 :            :                                              bool useRawSym)
     850                 :            : {
     851                 :        814 :   return getSymbolInternal(n.getKind(), n.getType(), name, useRawSym);
     852                 :            : }
     853                 :            : 
     854                 :    1211200 : Node LfscNodeConverter::getSymbolInternal(Kind k,
     855                 :            :                                           TypeNode tn,
     856                 :            :                                           const std::string& name,
     857                 :            :                                           bool useRawSym)
     858                 :            : {
     859                 :    2422400 :   std::tuple<Kind, TypeNode, std::string> key(k, tn, name);
     860                 :            :   std::map<std::tuple<Kind, TypeNode, std::string>, Node>::iterator it =
     861                 :    1211200 :       d_symbolsMap.find(key);
     862         [ +  + ]:    1211200 :   if (it != d_symbolsMap.end())
     863                 :            :   {
     864                 :    1162540 :     return it->second;
     865                 :            :   }
     866                 :      97326 :   Node sym = mkInternalSymbol(name, tn, useRawSym);
     867                 :      48663 :   d_symbolToBuiltinKind[sym] = k;
     868                 :      48663 :   d_symbolsMap[key] = sym;
     869                 :      48663 :   return sym;
     870                 :            : }
     871                 :            : 
     872                 :        970 : void LfscNodeConverter::getCharVectorInternal(Node c, std::vector<Node>& chars)
     873                 :            : {
     874 [ -  + ][ -  + ]:        970 :   Assert(c.getKind() == Kind::CONST_STRING);
                 [ -  - ]
     875                 :        970 :   const std::vector<unsigned>& vec = c.getConst<String>().getVec();
     876         [ +  + ]:        970 :   if (vec.size() == 0)
     877                 :            :   {
     878                 :        814 :     Node ec = getSymbolInternalFor(c, "emptystr");
     879                 :        407 :     chars.push_back(ec);
     880                 :        407 :     return;
     881                 :            :   }
     882                 :       1689 :   TypeNode tnc = d_nm->mkFunctionType(d_nm->integerType(), c.getType());
     883                 :       1689 :   Node aconstf = getSymbolInternal(Kind::CONST_STRING, tnc, "char");
     884         [ +  + ]:       3479 :   for (unsigned i = 0, size = vec.size(); i < size; i++)
     885                 :            :   {
     886                 :      14580 :     Node cc = mkApplyUf(aconstf, {d_nm->mkConstInt(Rational(vec[i]))});
     887                 :       2916 :     chars.push_back(cc);
     888                 :            :   }
     889                 :            : }
     890                 :            : 
     891                 :       1137 : Node LfscNodeConverter::convertBitVector(const BitVector& bv)
     892                 :            : {
     893                 :       2274 :   TypeNode btn = d_nm->booleanType();
     894                 :       5685 :   TypeNode btnv = d_nm->mkFunctionType({btn, btn}, btn);
     895                 :       1137 :   size_t w = bv.getSize();
     896                 :       2274 :   Node ret = getSymbolInternal(Kind::CONST_BITVECTOR, btn, "bvn");
     897                 :       3411 :   Node b0 = getSymbolInternal(Kind::CONST_BITVECTOR, btn, "b0");
     898                 :       3411 :   Node b1 = getSymbolInternal(Kind::CONST_BITVECTOR, btn, "b1");
     899                 :       3411 :   Node bvc = getSymbolInternal(Kind::CONST_BITVECTOR, btnv, "bvc");
     900         [ +  + ]:      19359 :   for (size_t i = 0; i < w; i++)
     901                 :            :   {
     902         [ +  + ]:      18222 :     Node arg = bv.isBitSet((w - 1) - i) ? b1 : b0;
     903 [ +  + ][ -  - ]:      54666 :     ret = mkApplyUf(bvc, {arg, ret});
     904                 :            :   }
     905                 :       2274 :   return ret;
     906                 :            : }
     907                 :            : 
     908                 :     687742 : Node LfscNodeConverter::getNullTerminator(Kind k, TypeNode tn)
     909                 :            : {
     910                 :    1375480 :   Node nullTerm;
     911    [ +  + ][ + ]:     687742 :   switch (k)
     912                 :            :   {
     913                 :        312 :     case Kind::REGEXP_CONCAT:
     914                 :            :       // the language containing only the empty string, which has special
     915                 :            :       // syntax in LFSC
     916                 :        312 :       nullTerm = getSymbolInternal(k, tn, "re.empty");
     917                 :        312 :       break;
     918                 :       5855 :     case Kind::BITVECTOR_CONCAT:
     919                 :            :     {
     920                 :            :       // the null terminator of bitvector concat is a dummy variable of
     921                 :            :       // bit-vector type with zero width, regardless of the type of the overall
     922                 :            :       // concat.
     923                 :       5855 :       TypeNode bvz = d_nm->mkBitVectorType(0);
     924                 :       5855 :       nullTerm = getSymbolInternal(k, bvz, "emptybv");
     925                 :            :     }
     926                 :       5855 :     break;
     927                 :     681575 :     default:
     928                 :            :       // no special handling, or not null terminated
     929                 :     681575 :       break;
     930                 :            :   }
     931         [ +  + ]:     687742 :   if (!nullTerm.isNull())
     932                 :            :   {
     933                 :       6167 :     return nullTerm;
     934                 :            :   }
     935                 :            :   // otherwise, fall back to standard utility
     936                 :     681575 :   return expr::getNullTerminator(k, tn);
     937                 :            : }
     938                 :            : 
     939                 :          0 : Kind LfscNodeConverter::getBuiltinKindForInternalSymbol(Node op) const
     940                 :            : {
     941                 :          0 :   std::map<Node, Kind>::const_iterator it = d_symbolToBuiltinKind.find(op);
     942         [ -  - ]:          0 :   if (it != d_symbolToBuiltinKind.end())
     943                 :            :   {
     944                 :          0 :     return it->second;
     945                 :            :   }
     946                 :          0 :   return Kind::UNDEFINED_KIND;
     947                 :            : }
     948                 :            : 
     949                 :     350312 : Node LfscNodeConverter::getOperatorOfTerm(Node n, bool macroApply)
     950                 :            : {
     951 [ -  + ][ -  + ]:     350312 :   Assert(n.hasOperator());
                 [ -  - ]
     952 [ -  + ][ -  + ]:     350312 :   Assert(!n.isClosure());
                 [ -  - ]
     953                 :     350312 :   Kind k = n.getKind();
     954                 :     700624 :   std::stringstream opName;
     955         [ +  - ]:     700624 :   Trace("lfsc-term-process-debug2")
     956                 :          0 :       << "getOperatorOfTerm " << n << " " << k << " "
     957                 :          0 :       << (n.getMetaKind() == metakind::PARAMETERIZED) << " "
     958                 :     350312 :       << GenericOp::isIndexedOperatorKind(k) << std::endl;
     959         [ +  + ]:     350312 :   if (n.getMetaKind() == metakind::PARAMETERIZED)
     960                 :            :   {
     961                 :     158652 :     Node op = n.getOperator();
     962                 :     158652 :     std::vector<Node> indices;
     963         [ +  + ]:      79326 :     if (GenericOp::isIndexedOperatorKind(k))
     964                 :            :     {
     965                 :      11419 :       indices = GenericOp::getIndicesForOperator(k, n.getOperator());
     966                 :            :       // we must convert the name of indices on updaters and testers
     967 [ +  + ][ +  + ]:      11419 :       if (k == Kind::APPLY_UPDATER || k == Kind::APPLY_TESTER)
     968                 :            :       {
     969 [ -  + ][ -  + ]:        582 :         Assert(indices.size() == 1);
                 [ -  - ]
     970                 :            :         // must convert to user name
     971                 :        582 :         TypeNode intType = d_nm->integerType();
     972                 :        582 :         indices[0] =
     973                 :       1164 :             getSymbolInternal(k, intType, getNameForUserNameOf(indices[0]));
     974                 :            :       }
     975                 :            :     }
     976         [ +  + ]:      67907 :     else if (op.getType().isFunction())
     977                 :            :     {
     978                 :      63969 :       return op;
     979                 :            :     }
     980                 :            :     // note other kinds of functions (e.g. selectors and testers)
     981                 :      30714 :     std::vector<TypeNode> argTypes;
     982         [ +  + ]:      32807 :     for (const Node& nc : n)
     983                 :            :     {
     984                 :      17450 :       argTypes.push_back(nc.getType());
     985                 :            :     }
     986                 :      30714 :     TypeNode ftype = n.getType();
     987         [ +  + ]:      15357 :     if (!argTypes.empty())
     988                 :            :     {
     989                 :      15260 :       ftype = d_nm->mkFunctionType(argTypes, ftype);
     990                 :            :     }
     991                 :      30714 :     Node ret;
     992         [ +  + ]:      15357 :     if (GenericOp::isIndexedOperatorKind(k))
     993                 :            :     {
     994                 :      22838 :       std::vector<TypeNode> itypes;
     995         [ +  + ]:      25424 :       for (const Node& i : indices)
     996                 :            :       {
     997                 :      14005 :         itypes.push_back(i.getType());
     998                 :            :       }
     999         [ +  - ]:      11419 :       if (!itypes.empty())
    1000                 :            :       {
    1001                 :      11419 :         ftype = d_nm->mkFunctionType(itypes, ftype);
    1002                 :            :       }
    1003         [ +  + ]:      11419 :       if (!macroApply)
    1004                 :            :       {
    1005 [ +  + ][ +  + ]:       1467 :         if (k != Kind::APPLY_UPDATER && k != Kind::APPLY_TESTER)
    1006                 :            :         {
    1007                 :       1392 :           opName << "f_";
    1008                 :            :         }
    1009                 :            :       }
    1010                 :            :       // must avoid overloading for to_fp variants
    1011         [ +  + ]:      11419 :       if (k == Kind::FLOATINGPOINT_TO_FP_FROM_FP)
    1012                 :            :       {
    1013                 :          1 :         opName << "to_fp_fp";
    1014                 :            :       }
    1015         [ -  + ]:      11418 :       else if (k == Kind::FLOATINGPOINT_TO_FP_FROM_IEEE_BV)
    1016                 :            :       {
    1017                 :          0 :         opName << "to_fp_ieee_bv";
    1018                 :            :       }
    1019         [ +  + ]:      11418 :       else if (k == Kind::FLOATINGPOINT_TO_FP_FROM_SBV)
    1020                 :            :       {
    1021                 :          4 :         opName << "to_fp_sbv";
    1022                 :            :       }
    1023         [ +  + ]:      11414 :       else if (k == Kind::FLOATINGPOINT_TO_FP_FROM_REAL)
    1024                 :            :       {
    1025                 :          2 :         opName << "to_fp_real";
    1026                 :            :       }
    1027         [ +  + ]:      11412 :       else if (k == Kind::BITVECTOR_BIT)
    1028                 :            :       {
    1029                 :       3605 :         opName << "bit";
    1030                 :            :       }
    1031                 :            :       else
    1032                 :            :       {
    1033                 :       7807 :         opName << printer::smt2::Smt2Printer::smtKindString(k);
    1034                 :            :       }
    1035                 :            :     }
    1036         [ +  + ]:       3938 :     else if (k == Kind::APPLY_CONSTRUCTOR)
    1037                 :            :     {
    1038                 :       2257 :       unsigned index = DType::indexOf(op);
    1039                 :       2257 :       const DType& dt = DType::datatypeOf(op);
    1040                 :            :       // get its variable name
    1041                 :       2257 :       opName << getNameForUserNameOf(dt[index].getConstructor());
    1042                 :            :     }
    1043         [ +  - ]:       1681 :     else if (k == Kind::APPLY_SELECTOR)
    1044                 :            :     {
    1045                 :       1681 :       ret = maybeMkSkolemFun(op, macroApply);
    1046         [ +  - ]:       1681 :       if (ret.isNull())
    1047                 :            :       {
    1048                 :       1681 :         unsigned index = DType::indexOf(op);
    1049                 :       1681 :         const DType& dt = DType::datatypeOf(op);
    1050                 :       1681 :         unsigned cindex = DType::cindexOf(op);
    1051                 :       1681 :         opName << getNameForUserNameOf(dt[cindex][index].getSelector());
    1052                 :            :       }
    1053                 :            :     }
    1054 [ -  - ][ -  - ]:          0 :     else if (k == Kind::SET_SINGLETON || k == Kind::BAG_MAKE
    1055         [ -  - ]:          0 :              || k == Kind::SEQ_UNIT)
    1056                 :            :     {
    1057         [ -  - ]:          0 :       if (!macroApply)
    1058                 :            :       {
    1059                 :          0 :         opName << "f_";
    1060                 :            :       }
    1061                 :          0 :       opName << printer::smt2::Smt2Printer::smtKindString(k);
    1062                 :            :     }
    1063                 :            :     else
    1064                 :            :     {
    1065                 :          0 :       opName << op;
    1066                 :            :     }
    1067         [ +  - ]:      15357 :     if (ret.isNull())
    1068                 :            :     {
    1069         [ +  - ]:      15357 :       Trace("lfsc-term-process-debug2") << "...default symbol" << std::endl;
    1070                 :      15357 :       ret = getSymbolInternal(k, ftype, opName.str());
    1071                 :            :     }
    1072                 :            :     // if indexed, apply to index
    1073         [ +  + ]:      15357 :     if (!indices.empty())
    1074                 :            :     {
    1075                 :      11419 :       ret = mkApplyUf(ret, indices);
    1076                 :            :     }
    1077         [ +  - ]:      15357 :     Trace("lfsc-term-process-debug2") << "...return " << ret << std::endl;
    1078                 :      15357 :     return ret;
    1079                 :            :   }
    1080                 :     541972 :   std::vector<TypeNode> argTypes;
    1081         [ +  + ]:     934259 :   for (const Node& nc : n)
    1082                 :            :   {
    1083                 :     663273 :     argTypes.push_back(nc.getType());
    1084                 :            :   }
    1085                 :            :   // we only use binary operators
    1086         [ +  + ]:     270986 :   if (NodeManager::isNAryKind(k))
    1087                 :            :   {
    1088                 :     118208 :     argTypes.resize(2);
    1089                 :            :   }
    1090                 :     541972 :   TypeNode tn = n.getType();
    1091                 :     270986 :   TypeNode ftype = d_nm->mkFunctionType(argTypes, tn);
    1092                 :            :   // most functions are called f_X where X is the SMT-LIB name, if we are
    1093                 :            :   // getting the macroApply variant, then we don't prefix with `f_`.
    1094         [ +  + ]:     270986 :   if (!macroApply)
    1095                 :            :   {
    1096                 :     212601 :     opName << "f_";
    1097                 :            :   }
    1098         [ +  + ]:     270986 :   if (k == Kind::FLOATINGPOINT_COMPONENT_NAN
    1099         [ +  + ]:     270984 :       || k == Kind::FLOATINGPOINT_COMPONENT_INF
    1100         [ +  + ]:     270983 :       || k == Kind::FLOATINGPOINT_COMPONENT_ZERO
    1101         [ +  + ]:     270982 :       || k == Kind::FLOATINGPOINT_COMPONENT_SIGN
    1102         [ +  + ]:     270980 :       || k == Kind::FLOATINGPOINT_COMPONENT_EXPONENT
    1103         [ +  + ]:     270979 :       || k == Kind::FLOATINGPOINT_COMPONENT_SIGNIFICAND
    1104         [ -  + ]:     270978 :       || k == Kind::ROUNDINGMODE_BITBLAST)
    1105                 :            :   {
    1106                 :            :     // remove @fp.
    1107                 :          8 :     std::string str = printer::smt2::Smt2Printer::smtKindString(k);
    1108                 :          8 :     opName << str.substr(4);
    1109                 :            :   }
    1110                 :            :   else
    1111                 :            :   {
    1112                 :            :     // all arithmetic kinds must explicitly deal with real vs int subtyping
    1113 [ +  + ][ +  + ]:     270978 :     if (k == Kind::ADD || k == Kind::MULT || k == Kind::NONLINEAR_MULT
                 [ +  + ]
    1114 [ +  + ][ +  + ]:     202276 :         || k == Kind::GEQ || k == Kind::GT || k == Kind::LEQ || k == Kind::LT
         [ +  + ][ +  + ]
    1115 [ +  + ][ +  + ]:     138777 :         || k == Kind::SUB || k == Kind::DIVISION || k == Kind::DIVISION_TOTAL
                 [ +  + ]
    1116 [ +  + ][ +  + ]:     136334 :         || k == Kind::INTS_DIVISION || k == Kind::INTS_DIVISION_TOTAL
    1117 [ +  + ][ +  + ]:     135825 :         || k == Kind::INTS_MODULUS || k == Kind::INTS_MODULUS_TOTAL
    1118 [ +  + ][ +  + ]:     135482 :         || k == Kind::NEG || k == Kind::POW)
    1119                 :            :     {
    1120                 :            :       // currently allow subtyping
    1121                 :     136023 :       opName << "a.";
    1122                 :            :     }
    1123         [ +  + ]:     270978 :     if (k == Kind::NEG)
    1124                 :            :     {
    1125                 :        522 :       opName << "u";
    1126                 :            :     }
    1127                 :     270978 :     opName << printer::smt2::Smt2Printer::smtKindString(k);
    1128                 :            :   }
    1129                 :     270986 :   return getSymbolInternal(k, ftype, opName.str());
    1130                 :            : }
    1131                 :            : 
    1132                 :      36510 : Node LfscNodeConverter::getOperatorOfClosure(Node q,
    1133                 :            :                                              bool macroApply,
    1134                 :            :                                              bool isPartial)
    1135                 :            : {
    1136                 :      73020 :   TypeNode retType = isPartial ? q[1].getType() : q.getType();
    1137                 :     109530 :   TypeNode bodyType = d_nm->mkFunctionType(q[1].getType(), retType);
    1138                 :            :   // We permit non-flat function types here
    1139                 :            :   // intType is used here for variable indices
    1140                 :      73020 :   TypeNode intType = d_nm->integerType();
    1141                 :     182550 :   TypeNode ftype = d_nm->mkFunctionType({intType, d_sortType}, bodyType);
    1142                 :      36510 :   Kind k = q.getKind();
    1143                 :      36510 :   std::stringstream opName;
    1144         [ +  + ]:      36510 :   if (!macroApply)
    1145                 :            :   {
    1146                 :       4652 :     opName << "f_";
    1147                 :            :   }
    1148                 :      36510 :   opName << printer::smt2::Smt2Printer::smtKindString(k);
    1149                 :      73020 :   return getSymbolInternal(k, ftype, opName.str());
    1150                 :            : }
    1151                 :            : 
    1152                 :      47896 : Node LfscNodeConverter::getOperatorOfBoundVar(Node cop, Node v)
    1153                 :            : {
    1154                 :     143688 :   Node x = d_nm->mkConstInt(Rational(getOrAssignIndexForBVar(v)));
    1155                 :      95792 :   Node tc = typeAsNode(convertType(v.getType()));
    1156 [ +  + ][ -  - ]:     191584 :   return mkApplyUf(cop, {x, tc});
    1157                 :            : }
    1158                 :            : 
    1159                 :      15733 : size_t LfscNodeConverter::getOrAssignIndexForFVar(Node fv)
    1160                 :            : {
    1161 [ -  + ][ -  + ]:      15733 :   Assert(fv.isVar());
                 [ -  - ]
    1162                 :      15733 :   std::map<Node, size_t>::iterator it = d_fvarIndex.find(fv);
    1163         [ -  + ]:      15733 :   if (it != d_fvarIndex.end())
    1164                 :            :   {
    1165                 :          0 :     return it->second;
    1166                 :            :   }
    1167                 :      15733 :   size_t id = d_fvarIndex.size();
    1168                 :      15733 :   d_fvarIndex[fv] = id;
    1169                 :      15733 :   return id;
    1170                 :            : }
    1171                 :            : 
    1172                 :      55686 : size_t LfscNodeConverter::getOrAssignIndexForBVar(Node bv)
    1173                 :            : {
    1174 [ -  + ][ -  + ]:      55686 :   Assert(bv.isVar());
                 [ -  - ]
    1175                 :      55686 :   std::map<Node, size_t>::iterator it = d_bvarIndex.find(bv);
    1176         [ +  + ]:      55686 :   if (it != d_bvarIndex.end())
    1177                 :            :   {
    1178                 :      47722 :     return it->second;
    1179                 :            :   }
    1180                 :       7964 :   size_t id = d_bvarIndex.size();
    1181                 :       7964 :   d_bvarIndex[bv] = id;
    1182                 :       7964 :   return id;
    1183                 :            : }
    1184                 :            : 
    1185                 :       1417 : const std::unordered_set<Node>& LfscNodeConverter::getDeclaredSymbols() const
    1186                 :            : {
    1187                 :       1417 :   return d_declVars;
    1188                 :            : }
    1189                 :            : 
    1190                 :       1417 : const std::unordered_set<TypeNode>& LfscNodeConverter::getDeclaredTypes() const
    1191                 :            : {
    1192                 :       1417 :   return d_declTypes;
    1193                 :            : }
    1194                 :            : 
    1195                 :            : }  // namespace proof
    1196                 :            : }  // namespace cvc5::internal

Generated by: LCOV version 1.14