1 /******************************************************************************
2 * Top contributors (to current version):
5 * This file is part of the cvc5 project.
7 * Copyright (c) 2009-2021 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 * ****************************************************************************
13 * Implementation of LFSC node conversion
16 #include "proof/lfsc/lfsc_node_converter.h"
20 #include "expr/array_store_all.h"
21 #include "expr/dtype.h"
22 #include "expr/dtype_cons.h"
23 #include "expr/nary_term_util.h"
24 #include "expr/node_manager_attributes.h"
25 #include "expr/sequence.h"
26 #include "expr/skolem_manager.h"
27 #include "printer/smt2/smt2_printer.h"
28 #include "theory/bv/theory_bv_utils.h"
29 #include "theory/strings/word.h"
30 #include "theory/uf/theory_uf_rewriter.h"
31 #include "util/bitvector.h"
32 #include "util/iand.h"
33 #include "util/rational.h"
34 #include "util/regexp.h"
35 #include "util/string.h"
37 using namespace cvc5::kind
;
42 LfscNodeConverter::LfscNodeConverter()
44 NodeManager
* nm
= NodeManager::currentNM();
45 d_arrow
= nm
->mkSortConstructor("arrow", 2);
47 d_sortType
= nm
->mkSort("sortType");
48 // the embedding of arrow into Node, which is binary constructor over sorts
49 TypeNode anfType
= nm
->mkFunctionType({d_sortType
, d_sortType
}, d_sortType
);
50 d_typeAsNode
[d_arrow
] = getSymbolInternal(FUNCTION_TYPE
, anfType
, "arrow");
52 TypeNode intType
= nm
->integerType();
53 TypeNode arrType
= nm
->mkFunctionType({d_sortType
, d_sortType
}, d_sortType
);
54 d_typeKindToNodeCons
[ARRAY_TYPE
] =
55 getSymbolInternal(FUNCTION_TYPE
, arrType
, "Array");
56 TypeNode bvType
= nm
->mkFunctionType(intType
, d_sortType
);
57 d_typeKindToNodeCons
[BITVECTOR_TYPE
] =
58 getSymbolInternal(FUNCTION_TYPE
, bvType
, "BitVec");
59 TypeNode fpType
= nm
->mkFunctionType({intType
, intType
}, d_sortType
);
60 d_typeKindToNodeCons
[FLOATINGPOINT_TYPE
] =
61 getSymbolInternal(FUNCTION_TYPE
, fpType
, "FloatingPoint");
62 TypeNode setType
= nm
->mkFunctionType(d_sortType
, d_sortType
);
63 d_typeKindToNodeCons
[SET_TYPE
] =
64 getSymbolInternal(FUNCTION_TYPE
, setType
, "Set");
65 d_typeKindToNodeCons
[BAG_TYPE
] =
66 getSymbolInternal(FUNCTION_TYPE
, setType
, "Bag");
67 d_typeKindToNodeCons
[SEQUENCE_TYPE
] =
68 getSymbolInternal(FUNCTION_TYPE
, setType
, "Seq");
71 Node
LfscNodeConverter::postConvert(Node n
)
73 NodeManager
* nm
= NodeManager::currentNM();
75 if (k
== ASCRIPTION_TYPE
)
77 // dummy node, return it
80 TypeNode tn
= n
.getType();
81 Trace("lfsc-term-process-debug")
82 << "postConvert " << n
<< " " << k
<< std::endl
;
83 if (k
== BOUND_VARIABLE
)
85 // ignore internally generated symbols
86 if (d_symbols
.find(n
) != d_symbols
.end())
90 // bound variable v is (bvar x T)
91 TypeNode intType
= nm
->integerType();
92 Node x
= nm
->mkConst(CONST_RATIONAL
, Rational(getOrAssignIndexForVar(n
)));
93 Node tc
= typeAsNode(convertType(tn
));
94 TypeNode ftype
= nm
->mkFunctionType({intType
, d_sortType
}, tn
);
95 Node bvarOp
= getSymbolInternal(k
, ftype
, "bvar");
96 return nm
->mkNode(APPLY_UF
, bvarOp
, x
, tc
);
98 else if (k
== SKOLEM
|| k
== BOOLEAN_TERM_VARIABLE
)
100 // constructors/selectors are represented by skolems, which are defined
102 if (tn
.isConstructor() || tn
.isSelector() || tn
.isTester()
105 // note these are not converted to their user named (cvc.) symbols here,
106 // to avoid type errors when constructing terms for postConvert
109 // skolems v print as their witness forms
110 // v is (skolem W) where W is the original or witness form of v
111 Node wi
= SkolemManager::getOriginalForm(n
);
114 // if it is not a purification skolem, maybe it is a witness skolem
115 wi
= SkolemManager::getWitnessForm(n
);
117 if (!wi
.isNull() && wi
!= n
)
119 Trace("lfsc-term-process-debug") << "...witness form " << wi
<< std::endl
;
121 Trace("lfsc-term-process-debug")
122 << "...converted witness for " << wi
<< std::endl
;
123 TypeNode ftype
= nm
->mkFunctionType(tn
, tn
);
124 Node skolemOp
= getSymbolInternal(k
, ftype
, "skolem");
125 return nm
->mkNode(APPLY_UF
, skolemOp
, wi
);
127 // might be a skolem function
128 Node ns
= maybeMkSkolemFun(n
);
133 // Otherwise, it is an uncategorized skolem, must use a fresh variable.
134 // This case will only apply for terms originating from places with no
136 TypeNode intType
= nm
->integerType();
137 TypeNode varType
= nm
->mkFunctionType({intType
, d_sortType
}, tn
);
138 Node var
= mkInternalSymbol("var", varType
);
140 nm
->mkConst(CONST_RATIONAL
, Rational(getOrAssignIndexForVar(n
)));
141 Node tc
= typeAsNode(convertType(tn
));
142 return nm
->mkNode(APPLY_UF
, var
, index
, tc
);
146 std::stringstream ss
;
148 Node nn
= mkInternalSymbol(getNameForUserName(ss
.str()), tn
);
151 else if (k
== APPLY_UF
)
153 return convert(theory::uf::TheoryUfRewriter::getHoApplyForApplyUf(n
));
155 else if (k
== APPLY_CONSTRUCTOR
|| k
== APPLY_SELECTOR
|| k
== APPLY_TESTER
156 || k
== APPLY_SELECTOR_TOTAL
|| k
== APPLY_UPDATER
)
158 // must convert other kinds of apply to functions, since we convert to
160 Node opc
= getOperatorOfTerm(n
, true);
161 if (n
.getNumChildren() == 0)
165 std::vector
<Node
> children
;
166 children
.push_back(opc
);
167 children
.insert(children
.end(), n
.begin(), n
.end());
168 return postConvert(nm
->mkNode(APPLY_UF
, children
));
170 else if (k
== HO_APPLY
)
172 std::vector
<TypeNode
> argTypes
;
173 argTypes
.push_back(n
[0].getType());
174 argTypes
.push_back(n
[1].getType());
175 TypeNode tnh
= nm
->mkFunctionType(argTypes
, tn
);
176 Node hconstf
= getSymbolInternal(k
, tnh
, "apply");
177 return nm
->mkNode(APPLY_UF
, hconstf
, n
[0], n
[1]);
179 else if (k
== CONST_RATIONAL
|| k
== CAST_TO_REAL
)
181 if (k
== CAST_TO_REAL
)
187 Assert(n
.getKind() == APPLY_UF
|| n
.getKind() == CONST_RATIONAL
);
188 } while (n
.getKind() != CONST_RATIONAL
);
190 TypeNode tnv
= nm
->mkFunctionType(tn
, tn
);
193 Rational r
= n
.getConst
<Rational
>();
196 rconstf
= getSymbolInternal(k
, tnv
, "int");
199 // use LFSC syntax for mpz negation
200 Node mpzn
= getSymbolInternal(k
, nm
->mkFunctionType(tn
, tn
), "~");
201 arg
= nm
->mkNode(APPLY_UF
, mpzn
, nm
->mkConst(CONST_RATIONAL
, r
.abs()));
210 rconstf
= getSymbolInternal(k
, tnv
, "real");
211 // ensure rationals are printed properly here using mpq syntax
212 // Note that inconvieniently, LFSC uses (non-sexpr) syntax n/m for
213 // constant rationals, hence we must use a string
214 std::stringstream ss
;
215 ss
<< "__LFSC_TMP" << r
.getNumerator().abs() << "/" << r
.getDenominator();
216 arg
= mkInternalSymbol(ss
.str(), tn
);
220 Node mpzn
= getSymbolInternal(k
, nm
->mkFunctionType(tn
, tn
), "~");
221 arg
= nm
->mkNode(APPLY_UF
, mpzn
, arg
);
224 return nm
->mkNode(APPLY_UF
, rconstf
, arg
);
226 else if (k
== CONST_BITVECTOR
)
228 TypeNode btn
= nm
->booleanType();
229 TypeNode tnv
= nm
->mkFunctionType(btn
, tn
);
230 TypeNode btnv
= nm
->mkFunctionType({btn
, btn
}, btn
);
231 BitVector bv
= n
.getConst
<BitVector
>();
232 size_t w
= bv
.getSize();
233 Node ret
= getSymbolInternal(k
, btn
, "bvn");
234 Node b0
= getSymbolInternal(k
, btn
, "b0");
235 Node b1
= getSymbolInternal(k
, btn
, "b1");
236 Node bvc
= getSymbolInternal(k
, btnv
, "bvc");
237 for (size_t i
= 0; i
< w
; i
++)
239 Node arg
= bv
.isBitSet((w
- 1) - i
) ? b1
: b0
;
240 ret
= nm
->mkNode(APPLY_UF
, bvc
, arg
, ret
);
242 Node bconstf
= getSymbolInternal(k
, tnv
, "bv");
243 return nm
->mkNode(APPLY_UF
, bconstf
, ret
);
245 else if (k
== CONST_STRING
)
249 //"ABC" is (str.++ (char 65) (str.++ (char 66) (str.++ (char 67) emptystr)))
250 std::vector
<Node
> charVec
;
251 getCharVectorInternal(n
, charVec
);
252 Assert(!charVec
.empty());
253 if (charVec
.size() == 1)
255 // handles empty string and singleton character
258 std::reverse(charVec
.begin(), charVec
.end());
259 Node ret
= postConvert(getNullTerminator(STRING_CONCAT
, tn
));
260 for (size_t i
= 0, size
= charVec
.size(); i
< size
; i
++)
262 ret
= nm
->mkNode(STRING_CONCAT
, charVec
[i
], ret
);
266 else if (k
== CONST_SEQUENCE
)
268 const std::vector
<Node
>& charVec
= n
.getConst
<Sequence
>().getVec();
269 TypeNode etype
= nm
->mkFunctionType(d_sortType
, tn
);
270 Node ret
= getSymbolInternal(k
, etype
, "seq.empty");
271 ret
= nm
->mkNode(APPLY_UF
, ret
, typeAsNode(convertType(tn
)));
272 std::vector
<Node
> vecu
;
273 for (size_t i
= 0, size
= charVec
.size(); i
< size
; i
++)
275 Node u
= nm
->mkNode(SEQ_UNIT
, postConvert(charVec
[size
- (i
+ 1)]));
281 ret
= nm
->mkNode(STRING_CONCAT
, u
, ret
);
285 else if (k
== STORE_ALL
)
287 Node t
= typeAsNode(convertType(tn
));
288 TypeNode caRetType
= nm
->mkFunctionType(tn
.getArrayConstituentType(), tn
);
289 TypeNode catype
= nm
->mkFunctionType(d_sortType
, caRetType
);
290 Node bconstf
= getSymbolInternal(k
, catype
, "array_const");
291 Node f
= nm
->mkNode(APPLY_UF
, bconstf
, t
);
292 ArrayStoreAll storeAll
= n
.getConst
<ArrayStoreAll
>();
293 return nm
->mkNode(APPLY_UF
, f
, convert(storeAll
.getValue()));
295 else if (k
== GEQ
|| k
== GT
|| k
== LEQ
|| k
== LT
|| k
== MINUS
296 || k
== DIVISION
|| k
== DIVISION_TOTAL
|| k
== INTS_DIVISION
297 || k
== INTS_DIVISION_TOTAL
|| k
== INTS_MODULUS
298 || k
== INTS_MODULUS_TOTAL
|| k
== UMINUS
|| k
== POW
299 || isIndexedOperatorKind(k
))
301 // must give special names to SMT-LIB operators with arithmetic subtyping
302 // note that MINUS is not n-ary
303 // get the macro-apply version of the operator
304 Node opc
= getOperatorOfTerm(n
, true);
305 std::vector
<Node
> children
;
306 children
.push_back(opc
);
307 children
.insert(children
.end(), n
.begin(), n
.end());
308 return nm
->mkNode(APPLY_UF
, children
);
310 else if (k
== SET_EMPTY
|| k
== SET_UNIVERSE
|| k
== BAG_EMPTY
)
312 Node t
= typeAsNode(convertType(tn
));
313 TypeNode etype
= nm
->mkFunctionType(d_sortType
, tn
);
314 Node ef
= getSymbolInternal(
317 k
== SET_EMPTY
? "set.empty"
318 : (k
== SET_UNIVERSE
? "set.universe" : "bag.empty"));
319 return nm
->mkNode(APPLY_UF
, ef
, t
);
321 else if (n
.isClosure())
323 // (forall ((x1 T1) ... (xn Tk)) P) is
324 // ((forall x1 T1) ((forall x2 T2) ... ((forall xk Tk) P))). We use
325 // SEXPR to do this, which avoids the need for indexed operators.
327 Node cop
= getOperatorOfClosure(n
, true);
328 for (size_t i
= 0, nchild
= n
[0].getNumChildren(); i
< nchild
; i
++)
330 size_t ii
= (nchild
- 1) - i
;
332 Node vop
= getOperatorOfBoundVar(cop
, v
);
333 ret
= nm
->mkNode(APPLY_UF
, vop
, ret
);
335 // notice that intentionally we drop annotations here
338 else if (k
== REGEXP_LOOP
)
340 // ((_ re.loop n1 n2) t) is ((re.loop n1 n2) t)
341 TypeNode intType
= nm
->integerType();
343 nm
->mkFunctionType({intType
, intType
}, nm
->mkFunctionType(tn
, tn
));
344 Node rop
= getSymbolInternal(
345 k
, relType
, printer::smt2::Smt2Printer::smtKindString(k
));
346 RegExpLoop op
= n
.getOperator().getConst
<RegExpLoop
>();
347 Node n1
= nm
->mkConst(CONST_RATIONAL
, Rational(op
.d_loopMinOcc
));
348 Node n2
= nm
->mkConst(CONST_RATIONAL
, Rational(op
.d_loopMaxOcc
));
349 return nm
->mkNode(APPLY_UF
, nm
->mkNode(APPLY_UF
, rop
, n1
, n2
), n
[0]);
353 // currently unsupported
356 else if (k
== BITVECTOR_BB_TERM
)
358 TypeNode btn
= nm
->booleanType();
359 // (bbT t1 ... tn) is (bbT t1 (bbT t2 ... (bbT tn emptybv)))
360 // where notice that each bbT has a different type
361 Node curr
= getNullTerminator(BITVECTOR_CONCAT
, tn
);
362 for (size_t i
= 0, nchild
= n
.getNumChildren(); i
< nchild
; ++i
)
364 TypeNode bvt
= nm
->mkBitVectorType(i
+ 1);
365 TypeNode ftype
= nm
->mkFunctionType({btn
, curr
.getType()}, bvt
);
366 Node bbt
= getSymbolInternal(k
, ftype
, "bbT");
367 curr
= nm
->mkNode(APPLY_UF
, bbt
, n
[nchild
- (i
+ 1)], curr
);
371 else if (k
== SEP_NIL
)
373 Node tnn
= typeAsNode(convertType(tn
));
374 TypeNode ftype
= nm
->mkFunctionType(d_sortType
, tn
);
375 Node s
= getSymbolInternal(k
, ftype
, "sep.nil");
376 return nm
->mkNode(APPLY_UF
, s
, tnn
);
378 else if (NodeManager::isNAryKind(k
) && n
.getNumChildren() >= 2)
380 size_t nchild
= n
.getNumChildren();
381 Assert(n
.getMetaKind() != metakind::PARAMETERIZED
);
382 // convert all n-ary applications to binary
383 std::vector
<Node
> children(n
.begin(), n
.end());
384 // distinct is special case
387 // DISTINCT(x1,...,xn) --->
388 // AND(DISTINCT(x1,x2), AND(,..., AND(,..,DISTINCT(x_{n-1},x_n))))
389 Node ret
= nm
->mkNode(k
, children
[0], children
[1]);
390 for (unsigned i
= 0; i
< nchild
; i
++)
391 for (unsigned j
= i
+ 1; j
< nchild
; j
++)
393 if (i
!= 0 && j
!= 1)
395 ret
= nm
->mkNode(AND
, ret
, nm
->mkNode(k
, children
[i
], children
[j
]));
398 Trace("lfsc-term-process-debug") << "n: " << n
<< std::endl
399 << "ret: " << ret
<< std::endl
;
402 std::reverse(children
.begin(), children
.end());
403 // Add the null-terminator. This is done to disambiguate the number
404 // of children for term with n-ary operators. In particular note that
405 // (or A B C (or D E)) has representation:
406 // (or A (or B (or C (or (or D E) false))))
407 // This makes the AST above distinguishable from (or A B C D E),
408 // which otherwise would both have representation:
409 // (or A (or B (or C (or D E))))
410 Node nullTerm
= getNullTerminator(k
, tn
);
411 // Most operators simply get binarized
414 if (nullTerm
.isNull())
421 // must convert recursively, since nullTerm may have subterms.
422 ret
= convert(nullTerm
);
426 // check whether we are also changing the operator name, in which case
427 // we build a binary uninterpreted function opc
429 if (k
== PLUS
|| k
== MULT
|| k
== NONLINEAR_MULT
)
431 std::stringstream opName
;
432 // currently allow subtyping
434 opName
<< printer::smt2::Smt2Printer::smtKindString(k
);
435 TypeNode ftype
= nm
->mkFunctionType({tn
, tn
}, tn
);
436 opc
= getSymbolInternal(k
, ftype
, opName
.str());
439 // now, iterate over children and make binary conversion
440 for (size_t i
= istart
, npchild
= children
.size(); i
< npchild
; i
++)
444 ret
= nm
->mkNode(ck
, opc
, children
[i
], ret
);
448 ret
= nm
->mkNode(ck
, children
[i
], ret
);
456 TypeNode
LfscNodeConverter::postConvertType(TypeNode tn
)
458 NodeManager
* nm
= NodeManager::currentNM();
461 Kind k
= tn
.getKind();
462 Trace("lfsc-term-process-debug")
463 << "postConvertType " << tn
<< " " << tn
.getNumChildren() << " " << k
465 if (k
== FUNCTION_TYPE
)
467 // (-> T1 ... Tn T) is (arrow T1 .... (arrow Tn T))
468 std::vector
<TypeNode
> argTypes
= tn
.getArgTypes();
469 // also make the node embedding of the type
470 Node arrown
= d_typeAsNode
[d_arrow
];
471 Assert(!arrown
.isNull());
472 cur
= tn
.getRangeType();
473 tnn
= typeAsNode(cur
);
474 for (std::vector
<TypeNode
>::reverse_iterator it
= argTypes
.rbegin();
475 it
!= argTypes
.rend();
478 std::vector
<TypeNode
> aargs
;
479 aargs
.push_back(*it
);
480 aargs
.push_back(cur
);
481 cur
= nm
->mkSort(d_arrow
, aargs
);
482 tnn
= nm
->mkNode(APPLY_UF
, arrown
, typeAsNode(*it
), tnn
);
485 else if (k
== BITVECTOR_TYPE
)
487 tnn
= d_typeKindToNodeCons
[k
];
488 Node w
= nm
->mkConst(CONST_RATIONAL
, Rational(tn
.getBitVectorSize()));
489 tnn
= nm
->mkNode(APPLY_UF
, tnn
, w
);
491 else if (k
== FLOATINGPOINT_TYPE
)
493 tnn
= d_typeKindToNodeCons
[k
];
494 Node e
= nm
->mkConst(CONST_RATIONAL
,
495 Rational(tn
.getFloatingPointExponentSize()));
496 Node s
= nm
->mkConst(CONST_RATIONAL
,
497 Rational(tn
.getFloatingPointSignificandSize()));
498 tnn
= nm
->mkNode(APPLY_UF
, tnn
, e
, s
);
500 else if (tn
.getNumChildren() == 0)
502 // special case: tuples must be distinguished by their arity
505 const DType
& dt
= tn
.getDType();
506 unsigned int nargs
= dt
[0].getNumArgs();
509 std::vector
<TypeNode
> types
;
510 std::vector
<TypeNode
> convTypes
;
511 std::vector
<Node
> targs
;
512 for (unsigned int i
= 0; i
< nargs
; i
++)
514 // it is not converted yet, convert here
515 TypeNode tnc
= convertType(dt
[0][i
].getRangeType());
516 types
.push_back(d_sortType
);
517 convTypes
.push_back(tnc
);
518 targs
.push_back(typeAsNode(tnc
));
520 TypeNode ftype
= nm
->mkFunctionType(types
, d_sortType
);
521 // must distinguish by arity
522 std::stringstream ss
;
523 ss
<< "Tuple_" << nargs
;
524 targs
.insert(targs
.begin(), getSymbolInternal(k
, ftype
, ss
.str()));
525 tnn
= nm
->mkNode(APPLY_UF
, targs
);
526 // we are changing its name, we must make a sort constructor
527 cur
= nm
->mkSortConstructor(ss
.str(), nargs
);
528 cur
= nm
->mkSort(cur
, convTypes
);
533 std::stringstream ss
;
534 options::ioutils::applyOutputLang(ss
, Language::LANG_SMTLIB_V2_6
);
536 if (tn
.isSort() || (tn
.isDatatype() && !tn
.isTuple()))
538 std::stringstream sss
;
539 sss
<< LfscNodeConverter::getNameForUserName(ss
.str());
540 tnn
= getSymbolInternal(k
, d_sortType
, sss
.str());
541 cur
= nm
->mkSort(sss
.str());
545 tnn
= getSymbolInternal(k
, d_sortType
, ss
.str());
551 // to build the type-as-node, must convert the component types
552 std::vector
<Node
> targs
;
553 std::vector
<TypeNode
> types
;
554 for (const TypeNode
& tnc
: tn
)
556 targs
.push_back(typeAsNode(tnc
));
557 types
.push_back(d_sortType
);
560 if (k
== PARAMETRIC_DATATYPE
)
562 // erase first child, which repeats the datatype
563 targs
.erase(targs
.begin(), targs
.begin() + 1);
564 types
.erase(types
.begin(), types
.begin() + 1);
565 TypeNode ftype
= nm
->mkFunctionType(types
, d_sortType
);
566 // the operator has been converted; it is no longer a datatype, thus
567 // we must print to get its name.
568 std::stringstream ss
;
570 op
= getSymbolInternal(k
, ftype
, ss
.str());
572 else if (k
== SORT_TYPE
)
574 TypeNode ftype
= nm
->mkFunctionType(types
, d_sortType
);
576 tn
.getAttribute(expr::VarNameAttr(), name
);
577 op
= getSymbolInternal(k
, ftype
, name
);
581 std::map
<Kind
, Node
>::iterator it
= d_typeKindToNodeCons
.find(k
);
582 if (it
!= d_typeKindToNodeCons
.end())
589 targs
.insert(targs
.begin(), op
);
590 tnn
= nm
->mkNode(APPLY_UF
, targs
);
597 Assert(!tnn
.isNull());
598 Trace("lfsc-term-process-debug") << "...type as node: " << tnn
<< std::endl
;
599 d_typeAsNode
[cur
] = tnn
;
603 std::string
LfscNodeConverter::getNameForUserName(const std::string
& name
)
605 std::stringstream ss
;
606 ss
<< "cvc." << name
;
610 bool LfscNodeConverter::shouldTraverse(Node n
)
612 Kind k
= n
.getKind();
613 // don't convert bound variable or instantiation pattern list directly
614 if (k
== BOUND_VAR_LIST
|| k
== INST_PATTERN_LIST
)
618 // should not traverse internal applications
621 if (d_symbols
.find(n
.getOperator()) != d_symbols
.end())
629 Node
LfscNodeConverter::maybeMkSkolemFun(Node k
, bool macroApply
)
631 NodeManager
* nm
= NodeManager::currentNM();
632 SkolemManager
* sm
= nm
->getSkolemManager();
633 SkolemFunId sfi
= SkolemFunId::NONE
;
635 TypeNode tn
= k
.getType();
636 if (sm
->isSkolemFunction(k
, sfi
, cacheVal
))
638 if (sfi
== SkolemFunId::SHARED_SELECTOR
)
640 // a skolem corresponding to shared selector should print in
641 // LFSC as (sel T n) where T is the type and n is the index of the
643 TypeNode fselt
= nm
->mkFunctionType(tn
.getSelectorDomainType(),
644 tn
.getSelectorRangeType());
645 TypeNode intType
= nm
->integerType();
646 TypeNode selt
= nm
->mkFunctionType({d_sortType
, intType
}, fselt
);
647 Node sel
= getSymbolInternal(k
.getKind(), selt
, "sel");
648 Node kn
= typeAsNode(convertType(tn
.getSelectorRangeType()));
649 Assert(!cacheVal
.isNull() && cacheVal
.getKind() == CONST_RATIONAL
);
650 return nm
->mkNode(APPLY_UF
, sel
, kn
, cacheVal
);
652 else if (sfi
== SkolemFunId::RE_UNFOLD_POS_COMPONENT
)
654 // a skolem corresponding to a regular expression unfolding component
655 // should print as (skolem_re_unfold_pos t R n) where the skolem is the
656 // n^th component for the unfolding of (str.in_re t R).
657 TypeNode strType
= nm
->stringType();
658 TypeNode reType
= nm
->regExpType();
659 TypeNode intType
= nm
->integerType();
660 TypeNode reut
= nm
->mkFunctionType({strType
, reType
, intType
}, strType
);
661 Node sk
= getSymbolInternal(k
.getKind(), reut
, "skolem_re_unfold_pos");
662 Assert(!cacheVal
.isNull() && cacheVal
.getKind() == SEXPR
663 && cacheVal
.getNumChildren() == 3);
664 // third value is mpz, which is not converted
667 {sk
, convert(cacheVal
[0]), convert(cacheVal
[1]), cacheVal
[2]});
673 Node
LfscNodeConverter::typeAsNode(TypeNode tni
) const
675 // should always exist in the cache, as we always run types through
676 // postConvertType before calling this method.
677 std::map
<TypeNode
, Node
>::const_iterator it
= d_typeAsNode
.find(tni
);
678 AlwaysAssert(it
!= d_typeAsNode
.end()) << "Missing typeAsNode " << tni
;
682 Node
LfscNodeConverter::mkInternalSymbol(const std::string
& name
, TypeNode tn
)
684 Node sym
= NodeManager::currentNM()->mkBoundVar(name
, tn
);
685 d_symbols
.insert(sym
);
689 Node
LfscNodeConverter::getSymbolInternalFor(Node n
, const std::string
& name
)
691 return getSymbolInternal(n
.getKind(), n
.getType(), name
);
694 Node
LfscNodeConverter::getSymbolInternal(Kind k
,
696 const std::string
& name
)
698 std::tuple
<Kind
, TypeNode
, std::string
> key(k
, tn
, name
);
699 std::map
<std::tuple
<Kind
, TypeNode
, std::string
>, Node
>::iterator it
=
700 d_symbolsMap
.find(key
);
701 if (it
!= d_symbolsMap
.end())
705 Node sym
= mkInternalSymbol(name
, tn
);
706 d_symbolToBuiltinKind
[sym
] = k
;
707 d_symbolsMap
[key
] = sym
;
711 void LfscNodeConverter::getCharVectorInternal(Node c
, std::vector
<Node
>& chars
)
713 Assert(c
.getKind() == CONST_STRING
);
714 NodeManager
* nm
= NodeManager::currentNM();
715 const std::vector
<unsigned>& vec
= c
.getConst
<String
>().getVec();
718 Node ec
= getSymbolInternalFor(c
, "emptystr");
722 TypeNode tnc
= nm
->mkFunctionType(nm
->integerType(), c
.getType());
723 Node aconstf
= getSymbolInternal(CONST_STRING
, tnc
, "char");
724 for (unsigned i
= 0, size
= vec
.size(); i
< size
; i
++)
726 Node cc
= nm
->mkNode(
727 APPLY_UF
, aconstf
, nm
->mkConst(CONST_RATIONAL
, Rational(vec
[i
])));
732 bool LfscNodeConverter::isIndexedOperatorKind(Kind k
)
734 return k
== BITVECTOR_EXTRACT
|| k
== BITVECTOR_REPEAT
735 || k
== BITVECTOR_ZERO_EXTEND
|| k
== BITVECTOR_SIGN_EXTEND
736 || k
== BITVECTOR_ROTATE_LEFT
|| k
== BITVECTOR_ROTATE_RIGHT
737 || k
== INT_TO_BITVECTOR
|| k
== IAND
|| k
== APPLY_UPDATER
738 || k
== APPLY_TESTER
;
741 std::vector
<Node
> LfscNodeConverter::getOperatorIndices(Kind k
, Node n
)
743 NodeManager
* nm
= NodeManager::currentNM();
744 std::vector
<Node
> indices
;
747 case BITVECTOR_EXTRACT
:
749 BitVectorExtract p
= n
.getConst
<BitVectorExtract
>();
750 indices
.push_back(nm
->mkConst(CONST_RATIONAL
, Rational(p
.d_high
)));
751 indices
.push_back(nm
->mkConst(CONST_RATIONAL
, Rational(p
.d_low
)));
754 case BITVECTOR_REPEAT
:
756 nm
->mkConst(CONST_RATIONAL
,
757 Rational(n
.getConst
<BitVectorRepeat
>().d_repeatAmount
)));
759 case BITVECTOR_ZERO_EXTEND
:
760 indices
.push_back(nm
->mkConst(
762 Rational(n
.getConst
<BitVectorZeroExtend
>().d_zeroExtendAmount
)));
764 case BITVECTOR_SIGN_EXTEND
:
765 indices
.push_back(nm
->mkConst(
767 Rational(n
.getConst
<BitVectorSignExtend
>().d_signExtendAmount
)));
769 case BITVECTOR_ROTATE_LEFT
:
770 indices
.push_back(nm
->mkConst(
772 Rational(n
.getConst
<BitVectorRotateLeft
>().d_rotateLeftAmount
)));
774 case BITVECTOR_ROTATE_RIGHT
:
775 indices
.push_back(nm
->mkConst(
777 Rational(n
.getConst
<BitVectorRotateRight
>().d_rotateRightAmount
)));
779 case INT_TO_BITVECTOR
:
780 indices
.push_back(nm
->mkConst(
781 CONST_RATIONAL
, Rational(n
.getConst
<IntToBitVector
>().d_size
)));
785 nm
->mkConst(CONST_RATIONAL
, Rational(n
.getConst
<IntAnd
>().d_size
)));
789 unsigned index
= DType::indexOf(n
);
790 const DType
& dt
= DType::datatypeOf(n
);
791 indices
.push_back(dt
[index
].getConstructor());
796 unsigned index
= DType::indexOf(n
);
797 const DType
& dt
= DType::datatypeOf(n
);
798 unsigned cindex
= DType::cindexOf(n
);
799 indices
.push_back(dt
[cindex
][index
].getSelector());
802 default: Assert(false); break;
807 Node
LfscNodeConverter::getNullTerminator(Kind k
, TypeNode tn
)
809 NodeManager
* nm
= NodeManager::currentNM();
814 // the language containing only the empty string, which has special
816 nullTerm
= getSymbolInternal(k
, tn
, "re.empty");
818 case BITVECTOR_CONCAT
:
820 // the null terminator of bitvector concat is a dummy variable of
821 // bit-vector type with zero width, regardless of the type of the overall
823 TypeNode bvz
= nm
->mkBitVectorType(0);
824 nullTerm
= getSymbolInternal(k
, bvz
, "emptybv");
828 // no special handling, or not null terminated
831 if (!nullTerm
.isNull())
835 // otherwise, fall back to standard utility
836 return expr::getNullTerminator(k
, tn
);
839 Kind
LfscNodeConverter::getBuiltinKindForInternalSymbol(Node op
) const
841 std::map
<Node
, Kind
>::const_iterator it
= d_symbolToBuiltinKind
.find(op
);
842 if (it
!= d_symbolToBuiltinKind
.end())
846 return UNDEFINED_KIND
;
849 Node
LfscNodeConverter::getOperatorOfTerm(Node n
, bool macroApply
)
851 Assert(n
.hasOperator());
852 Assert(!n
.isClosure());
853 NodeManager
* nm
= NodeManager::currentNM();
854 Kind k
= n
.getKind();
855 std::stringstream opName
;
856 Trace("lfsc-term-process-debug2")
857 << "getOperatorOfTerm " << n
<< " " << k
<< " "
858 << (n
.getMetaKind() == metakind::PARAMETERIZED
) << " "
859 << isIndexedOperatorKind(k
) << std::endl
;
860 if (n
.getMetaKind() == metakind::PARAMETERIZED
)
862 Node op
= n
.getOperator();
863 std::vector
<Node
> indices
;
864 if (isIndexedOperatorKind(k
))
866 indices
= getOperatorIndices(k
, n
.getOperator());
867 // we must convert the name of indices on updaters and testers
868 if (k
== APPLY_UPDATER
|| k
== APPLY_TESTER
)
870 Assert(indices
.size() == 1);
871 // must convert to user name
872 std::stringstream sss
;
874 TypeNode intType
= nm
->integerType();
876 getSymbolInternal(k
, intType
, getNameForUserName(sss
.str()));
879 else if (op
.getType().isFunction())
883 // note other kinds of functions (e.g. selectors and testers)
884 std::vector
<TypeNode
> argTypes
;
885 for (const Node
& nc
: n
)
887 argTypes
.push_back(nc
.getType());
889 TypeNode ftype
= n
.getType();
890 if (!argTypes
.empty())
892 ftype
= nm
->mkFunctionType(argTypes
, ftype
);
895 if (isIndexedOperatorKind(k
))
897 std::vector
<TypeNode
> itypes
;
898 for (const Node
& i
: indices
)
900 itypes
.push_back(i
.getType());
904 ftype
= nm
->mkFunctionType(itypes
, ftype
);
908 if (k
!= APPLY_UPDATER
&& k
!= APPLY_TESTER
)
913 opName
<< printer::smt2::Smt2Printer::smtKindString(k
);
915 else if (k
== APPLY_CONSTRUCTOR
)
917 unsigned index
= DType::indexOf(op
);
918 const DType
& dt
= DType::datatypeOf(op
);
919 std::stringstream ssc
;
920 ssc
<< dt
[index
].getConstructor();
921 opName
<< getNameForUserName(ssc
.str());
923 else if (k
== APPLY_SELECTOR
)
925 unsigned index
= DType::indexOf(op
);
926 const DType
& dt
= DType::datatypeOf(op
);
927 unsigned cindex
= DType::cindexOf(op
);
928 std::stringstream sss
;
929 sss
<< dt
[cindex
][index
].getSelector();
930 opName
<< getNameForUserName(sss
.str());
932 else if (k
== APPLY_SELECTOR_TOTAL
)
934 ret
= maybeMkSkolemFun(op
, macroApply
);
935 Assert(!ret
.isNull());
937 else if (k
== SET_SINGLETON
|| k
== BAG_MAKE
)
943 opName
<< printer::smt2::Smt2Printer::smtKindString(k
);
951 ret
= getSymbolInternal(k
, ftype
, opName
.str());
953 // if indexed, apply to index
954 if (!indices
.empty())
956 std::vector
<Node
> ichildren
;
957 ichildren
.push_back(ret
);
958 ichildren
.insert(ichildren
.end(), indices
.begin(), indices
.end());
959 ret
= nm
->mkNode(APPLY_UF
, ichildren
);
961 Trace("lfsc-term-process-debug2") << "...return " << ret
<< std::endl
;
964 std::vector
<TypeNode
> argTypes
;
965 for (const Node
& nc
: n
)
967 argTypes
.push_back(nc
.getType());
969 // we only use binary operators
970 if (NodeManager::isNAryKind(k
))
974 TypeNode tn
= n
.getType();
975 TypeNode ftype
= nm
->mkFunctionType(argTypes
, tn
);
976 // most functions are called f_X where X is the SMT-LIB name, if we are
977 // getting the macroApply variant, then we don't prefix with `f_`.
982 // all arithmetic kinds must explicitly deal with real vs int subtyping
983 if (k
== PLUS
|| k
== MULT
|| k
== NONLINEAR_MULT
|| k
== GEQ
|| k
== GT
984 || k
== LEQ
|| k
== LT
|| k
== MINUS
|| k
== DIVISION
985 || k
== DIVISION_TOTAL
|| k
== INTS_DIVISION
|| k
== INTS_DIVISION_TOTAL
986 || k
== INTS_MODULUS
|| k
== INTS_MODULUS_TOTAL
|| k
== UMINUS
989 // currently allow subtyping
996 opName
<< printer::smt2::Smt2Printer::smtKindString(k
);
997 if (k
== DIVISION_TOTAL
|| k
== INTS_DIVISION_TOTAL
998 || k
== INTS_MODULUS_TOTAL
)
1002 return getSymbolInternal(k
, ftype
, opName
.str());
1005 Node
LfscNodeConverter::getOperatorOfClosure(Node q
, bool macroApply
)
1007 NodeManager
* nm
= NodeManager::currentNM();
1008 TypeNode bodyType
= nm
->mkFunctionType(q
[1].getType(), q
.getType());
1009 // We permit non-flat function types here
1010 // intType is used here for variable indices
1011 TypeNode intType
= nm
->integerType();
1012 TypeNode ftype
= nm
->mkFunctionType({intType
, d_sortType
}, bodyType
);
1013 Kind k
= q
.getKind();
1014 std::stringstream opName
;
1019 opName
<< printer::smt2::Smt2Printer::smtKindString(k
);
1020 return getSymbolInternal(k
, ftype
, opName
.str());
1023 Node
LfscNodeConverter::getOperatorOfBoundVar(Node cop
, Node v
)
1025 NodeManager
* nm
= NodeManager::currentNM();
1026 Node x
= nm
->mkConst(CONST_RATIONAL
, Rational(getOrAssignIndexForVar(v
)));
1027 Node tc
= typeAsNode(convertType(v
.getType()));
1028 return nm
->mkNode(APPLY_UF
, cop
, x
, tc
);
1031 size_t LfscNodeConverter::getOrAssignIndexForVar(Node v
)
1034 std::map
<Node
, size_t>::iterator it
= d_varIndex
.find(v
);
1035 if (it
!= d_varIndex
.end())
1039 size_t id
= d_varIndex
.size();
1044 } // namespace proof