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: 687 713 96.4 %
Date: 2026-03-28 10:41:09 Functions: 25 26 96.2 %
Branches: 425 547 77.7 %

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

Generated by: LCOV version 1.14