1 /********************* */
2 /*! \file evaluator.cpp
4 ** Top contributors (to current version):
5 ** Andres Noetzli, Andrew Reynolds
6 ** This file is part of the CVC4 project.
7 ** Copyright (c) 2009-2020 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.\endverbatim
12 ** \brief The Evaluator class
14 ** The Evaluator class.
17 #include "theory/evaluator.h"
19 #include "theory/bv/theory_bv_utils.h"
20 #include "theory/rewriter.h"
21 #include "theory/strings/theory_strings_utils.h"
22 #include "theory/theory.h"
23 #include "util/integer.h"
28 EvalResult::EvalResult(const EvalResult
& other
)
33 case BOOL
: d_bool
= other
.d_bool
; break;
35 new (&d_bv
) BitVector
;
39 new (&d_rat
) Rational
;
48 UninterpretedConstant(other
.d_uc
.getType(), other
.d_uc
.getIndex());
54 EvalResult
& EvalResult::operator=(const EvalResult
& other
)
61 case BOOL
: d_bool
= other
.d_bool
; break;
63 new (&d_bv
) BitVector
;
67 new (&d_rat
) Rational
;
76 UninterpretedConstant(other
.d_uc
.getType(), other
.d_uc
.getIndex());
84 EvalResult::~EvalResult()
105 d_uc
.~UninterpretedConstant();
112 Node
EvalResult::toNode() const
114 NodeManager
* nm
= NodeManager::currentNM();
117 case EvalResult::BOOL
: return nm
->mkConst(d_bool
);
118 case EvalResult::BITVECTOR
: return nm
->mkConst(d_bv
);
119 case EvalResult::RATIONAL
: return nm
->mkConst(d_rat
);
120 case EvalResult::STRING
: return nm
->mkConst(d_str
);
121 case EvalResult::UCONST
: return nm
->mkConst(d_uc
);
124 Trace("evaluator") << "Missing conversion from " << d_tag
<< " to node"
131 Node
Evaluator::eval(TNode n
,
132 const std::vector
<Node
>& args
,
133 const std::vector
<Node
>& vals
,
134 bool useRewriter
) const
136 std::unordered_map
<Node
, Node
, NodeHashFunction
> visited
;
137 return eval(n
, args
, vals
, visited
, useRewriter
);
139 Node
Evaluator::eval(
141 const std::vector
<Node
>& args
,
142 const std::vector
<Node
>& vals
,
143 const std::unordered_map
<Node
, Node
, NodeHashFunction
>& visited
,
144 bool useRewriter
) const
146 Trace("evaluator") << "Evaluating " << n
<< " under substitution " << args
147 << " " << vals
<< " with visited size = " << visited
.size()
149 std::unordered_map
<TNode
, Node
, NodeHashFunction
> evalAsNode
;
150 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
> results
;
151 // add visited to results
152 for (const std::pair
<const Node
, Node
>& p
: visited
)
154 Trace("evaluator") << "Add " << p
.first
<< " == " << p
.second
<< std::endl
;
155 results
[p
.first
] = evalInternal(p
.second
, args
, vals
, evalAsNode
, results
, useRewriter
);
156 if (results
[p
.first
].d_tag
== EvalResult::INVALID
)
158 // could not evaluate, use the evalAsNode map
159 std::unordered_map
<TNode
, Node
, NodeHashFunction
>::iterator itn
=
160 evalAsNode
.find(p
.second
);
161 Assert(itn
!= evalAsNode
.end());
162 Node val
= itn
->second
;
165 val
= Rewriter::rewrite(val
);
167 evalAsNode
[p
.first
] = val
;
170 Trace("evaluator") << "Run eval internal..." << std::endl
;
171 Node ret
= evalInternal(n
, args
, vals
, evalAsNode
, results
, useRewriter
).toNode();
172 // if we failed to evaluate
173 if (ret
.isNull() && useRewriter
)
175 // should be stored in the evaluation-as-node map
176 std::unordered_map
<TNode
, Node
, NodeHashFunction
>::iterator itn
=
178 Assert(itn
!= evalAsNode
.end());
179 ret
= Rewriter::rewrite(itn
->second
);
181 // should be the same as substitution + rewriting, or possibly null if
182 // useRewriter is false
183 Assert((ret
.isNull() && !useRewriter
)
185 == Rewriter::rewrite(n
.substitute(
186 args
.begin(), args
.end(), vals
.begin(), vals
.end())));
190 EvalResult
Evaluator::evalInternal(
192 const std::vector
<Node
>& args
,
193 const std::vector
<Node
>& vals
,
194 std::unordered_map
<TNode
, Node
, NodeHashFunction
>& evalAsNode
,
195 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>& results
,
196 bool useRewriter
) const
198 std::vector
<TNode
> queue
;
199 queue
.emplace_back(n
);
200 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>::iterator itr
;
202 while (queue
.size() != 0)
204 TNode currNode
= queue
.back();
206 if (results
.find(currNode
) != results
.end())
212 bool doProcess
= true;
215 if (currNode
.isVar())
217 // we do not evaluate if we are a variable, instead we look for the
218 // variable in args below
222 else if (currNode
.getMetaKind() == kind::metakind::PARAMETERIZED
)
224 TNode op
= currNode
.getOperator();
225 // Certain nodes are parameterized with constant operators, including
226 // bitvector extract. These operators do not need to be evaluated.
229 itr
= results
.find(op
);
230 if (itr
== results
.end())
232 queue
.emplace_back(op
);
235 else if (itr
->second
.d_tag
== EvalResult::INVALID
)
241 for (const auto& currNodeChild
: currNode
)
243 itr
= results
.find(currNodeChild
);
244 if (itr
== results
.end())
246 queue
.emplace_back(currNodeChild
);
249 else if (itr
->second
.d_tag
== EvalResult::INVALID
)
251 // we cannot evaluate since there was an invalid child
255 Trace("evaluator") << "Evaluator: visit " << currNode
256 << ", process = " << doProcess
257 << ", evaluate = " << doEval
<< std::endl
;
263 Node currNodeVal
= currNode
;
264 // whether we need to reconstruct the current node in the case of failure
265 bool needsReconstruct
= true;
267 // The code below should either:
268 // (1) store a valid EvalResult into results[currNode], or
269 // (2) store an invalid EvalResult into results[currNode] and
270 // store the result of substitution + rewriting currNode { args -> vals }
271 // into evalAsNode[currNode].
273 // If we did not successfully evaluate all children, or are a variable
278 const auto& it
= std::find(args
.begin(), args
.end(), currNode
);
279 if (it
== args
.end())
281 // variable with no substitution is itself
282 evalAsNode
[currNode
] = currNode
;
283 results
[currNode
] = EvalResult();
286 ptrdiff_t pos
= std::distance(args
.begin(), it
);
287 currNodeVal
= vals
[pos
];
288 // Don't need to rewrite since range of substitution should already
293 // Reconstruct the node with a combination of the children that
294 // successfully evaluated, and the children that did not.
295 Trace("evaluator") << "Evaluator: collect arguments" << std::endl
;
296 currNodeVal
= reconstruct(currNodeVal
, results
, evalAsNode
);
299 // Rewrite the result now, if we use the rewriter. We will see below
300 // if we are able to turn it into a valid EvalResult.
301 currNodeVal
= Rewriter::rewrite(currNodeVal
);
304 needsReconstruct
= false;
305 Trace("evaluator") << "Evaluator: now after substitution + rewriting: "
306 << currNodeVal
<< std::endl
;
307 if (currNodeVal
.getNumChildren() > 0)
309 // We may continue with a valid EvalResult at this point only if
310 // we have no children. We must otherwise fail here since some of
311 // our children may not have successful evaluations.
312 results
[currNode
] = EvalResult();
313 evalAsNode
[currNode
] = currNodeVal
;
316 // Otherwise, we may be able to turn the overall result into an
317 // valid EvalResult and continue. We fallthrough and continue with the
318 // block of code below.
321 Trace("evaluator") << "Current node val : " << currNodeVal
<< std::endl
;
323 switch (currNodeVal
.getKind())
325 // APPLY_UF is a special case where we look up the operator and apply
326 // beta reduction if possible
329 Trace("evaluator") << "Evaluate " << currNode
<< std::endl
;
330 TNode op
= currNode
.getOperator();
331 Assert(evalAsNode
.find(op
) != evalAsNode
.end());
332 // no function can be a valid EvalResult
334 Trace("evaluator") << "Operator evaluated to " << op
<< std::endl
;
335 if (op
.getKind() != kind::LAMBDA
)
337 // this node is not evaluatable due to operator, must add to
339 results
[currNode
] = EvalResult();
340 evalAsNode
[currNode
] = reconstruct(currNode
, results
, evalAsNode
);
343 // Create a copy of the current substitutions
344 std::vector
<Node
> lambdaArgs(args
);
345 std::vector
<Node
> lambdaVals(vals
);
347 // Add the values for the arguments of the lambda as substitutions at
348 // the beginning of the vector to shadow variables from outer scopes
349 // with the same name
350 for (const auto& lambdaArg
: op
[0])
352 lambdaArgs
.insert(lambdaArgs
.begin(), lambdaArg
);
355 for (const auto& lambdaVal
: currNode
)
357 lambdaVals
.insert(lambdaVals
.begin(), results
[lambdaVal
].toNode());
360 // Lambdas are evaluated in a recursive fashion because each
361 // evaluation requires different substitutions. We use a fresh cache
362 // since the evaluation of op[1] is under a new substitution and thus
363 // should not be cached. We could alternatively copy evalAsNode to
364 // evalAsNodeC but favor avoiding this copy for performance reasons.
365 std::unordered_map
<TNode
, Node
, NodeHashFunction
> evalAsNodeC
;
366 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
> resultsC
;
367 results
[currNode
] = evalInternal(op
[1],
373 Trace("evaluator") << "Evaluated via arguments to "
374 << results
[currNode
].d_tag
<< std::endl
;
375 if (results
[currNode
].d_tag
== EvalResult::INVALID
)
377 // evaluation was invalid, we take the node of op[1] as the result
378 evalAsNode
[currNode
] = evalAsNodeC
[op
[1]];
380 << "Take node evaluation: " << evalAsNodeC
[op
[1]] << std::endl
;
384 case kind::CONST_BOOLEAN
:
385 results
[currNode
] = EvalResult(currNodeVal
.getConst
<bool>());
390 results
[currNode
] = EvalResult(!(results
[currNode
[0]].d_bool
));
396 bool res
= results
[currNode
[0]].d_bool
;
397 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
399 res
= res
&& results
[currNode
[i
]].d_bool
;
401 results
[currNode
] = EvalResult(res
);
407 bool res
= results
[currNode
[0]].d_bool
;
408 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
410 res
= res
|| results
[currNode
[i
]].d_bool
;
412 results
[currNode
] = EvalResult(res
);
416 case kind::CONST_RATIONAL
:
418 const Rational
& r
= currNodeVal
.getConst
<Rational
>();
419 results
[currNode
] = EvalResult(r
);
422 case kind::UNINTERPRETED_CONSTANT
:
424 const UninterpretedConstant
& uc
=
425 currNodeVal
.getConst
<UninterpretedConstant
>();
426 results
[currNode
] = EvalResult(uc
);
431 Rational res
= results
[currNode
[0]].d_rat
;
432 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
434 res
= res
+ results
[currNode
[i
]].d_rat
;
436 results
[currNode
] = EvalResult(res
);
442 const Rational
& x
= results
[currNode
[0]].d_rat
;
443 const Rational
& y
= results
[currNode
[1]].d_rat
;
444 results
[currNode
] = EvalResult(x
- y
);
450 const Rational
& x
= results
[currNode
[0]].d_rat
;
451 results
[currNode
] = EvalResult(-x
);
455 case kind::NONLINEAR_MULT
:
457 Rational res
= results
[currNode
[0]].d_rat
;
458 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
460 res
= res
* results
[currNode
[i
]].d_rat
;
462 results
[currNode
] = EvalResult(res
);
468 const Rational
& x
= results
[currNode
[0]].d_rat
;
469 const Rational
& y
= results
[currNode
[1]].d_rat
;
470 results
[currNode
] = EvalResult(x
>= y
);
475 const Rational
& x
= results
[currNode
[0]].d_rat
;
476 const Rational
& y
= results
[currNode
[1]].d_rat
;
477 results
[currNode
] = EvalResult(x
<= y
);
482 const Rational
& x
= results
[currNode
[0]].d_rat
;
483 const Rational
& y
= results
[currNode
[1]].d_rat
;
484 results
[currNode
] = EvalResult(x
> y
);
489 const Rational
& x
= results
[currNode
[0]].d_rat
;
490 const Rational
& y
= results
[currNode
[1]].d_rat
;
491 results
[currNode
] = EvalResult(x
< y
);
496 const Rational
& x
= results
[currNode
[0]].d_rat
;
497 results
[currNode
] = EvalResult(x
.abs());
500 case kind::CONST_STRING
:
501 results
[currNode
] = EvalResult(currNodeVal
.getConst
<String
>());
504 case kind::STRING_CONCAT
:
506 String res
= results
[currNode
[0]].d_str
;
507 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
509 res
= res
.concat(results
[currNode
[i
]].d_str
);
511 results
[currNode
] = EvalResult(res
);
515 case kind::STRING_LENGTH
:
517 const String
& s
= results
[currNode
[0]].d_str
;
518 results
[currNode
] = EvalResult(Rational(s
.size()));
522 case kind::STRING_SUBSTR
:
524 const String
& s
= results
[currNode
[0]].d_str
;
525 Integer
s_len(s
.size());
526 Integer i
= results
[currNode
[1]].d_rat
.getNumerator();
527 Integer j
= results
[currNode
[2]].d_rat
.getNumerator();
529 if (i
.strictlyNegative() || j
.strictlyNegative() || i
>= s_len
)
531 results
[currNode
] = EvalResult(String(""));
533 else if (i
+ j
> s_len
)
536 EvalResult(s
.suffix((s_len
- i
).toUnsignedInt()));
541 EvalResult(s
.substr(i
.toUnsignedInt(), j
.toUnsignedInt()));
546 case kind::STRING_UPDATE
:
548 const String
& s
= results
[currNode
[0]].d_str
;
549 Integer
s_len(s
.size());
550 Integer i
= results
[currNode
[1]].d_rat
.getNumerator();
551 const String
& t
= results
[currNode
[2]].d_str
;
553 if (i
.strictlyNegative() || i
>= s_len
)
555 results
[currNode
] = EvalResult(s
);
559 results
[currNode
] = EvalResult(s
.update(i
.toUnsignedInt(), t
));
563 case kind::STRING_CHARAT
:
565 const String
& s
= results
[currNode
[0]].d_str
;
566 Integer
s_len(s
.size());
567 Integer i
= results
[currNode
[1]].d_rat
.getNumerator();
568 if (i
.strictlyNegative() || i
>= s_len
)
570 results
[currNode
] = EvalResult(String(""));
574 results
[currNode
] = EvalResult(s
.substr(i
.toUnsignedInt(), 1));
579 case kind::STRING_STRCTN
:
581 const String
& s
= results
[currNode
[0]].d_str
;
582 const String
& t
= results
[currNode
[1]].d_str
;
583 results
[currNode
] = EvalResult(s
.find(t
) != std::string::npos
);
587 case kind::STRING_STRIDOF
:
589 const String
& s
= results
[currNode
[0]].d_str
;
590 Integer
s_len(s
.size());
591 const String
& x
= results
[currNode
[1]].d_str
;
592 Integer i
= results
[currNode
[2]].d_rat
.getNumerator();
594 if (i
.strictlyNegative())
596 results
[currNode
] = EvalResult(Rational(-1));
600 size_t r
= s
.find(x
, i
.toUnsignedInt());
601 if (r
== std::string::npos
)
603 results
[currNode
] = EvalResult(Rational(-1));
607 results
[currNode
] = EvalResult(Rational(r
));
613 case kind::STRING_STRREPL
:
615 const String
& s
= results
[currNode
[0]].d_str
;
616 const String
& x
= results
[currNode
[1]].d_str
;
617 const String
& y
= results
[currNode
[2]].d_str
;
618 results
[currNode
] = EvalResult(s
.replace(x
, y
));
622 case kind::STRING_PREFIX
:
624 const String
& t
= results
[currNode
[0]].d_str
;
625 const String
& s
= results
[currNode
[1]].d_str
;
626 if (s
.size() < t
.size())
628 results
[currNode
] = EvalResult(false);
632 results
[currNode
] = EvalResult(s
.prefix(t
.size()) == t
);
637 case kind::STRING_SUFFIX
:
639 const String
& t
= results
[currNode
[0]].d_str
;
640 const String
& s
= results
[currNode
[1]].d_str
;
641 if (s
.size() < t
.size())
643 results
[currNode
] = EvalResult(false);
647 results
[currNode
] = EvalResult(s
.suffix(t
.size()) == t
);
652 case kind::STRING_ITOS
:
654 Integer i
= results
[currNode
[0]].d_rat
.getNumerator();
655 if (i
.strictlyNegative())
657 results
[currNode
] = EvalResult(String(""));
661 results
[currNode
] = EvalResult(String(i
.toString()));
666 case kind::STRING_STOI
:
668 const String
& s
= results
[currNode
[0]].d_str
;
671 results
[currNode
] = EvalResult(Rational(s
.toNumber()));
675 results
[currNode
] = EvalResult(Rational(-1));
680 case kind::STRING_FROM_CODE
:
682 Integer i
= results
[currNode
[0]].d_rat
.getNumerator();
683 if (i
>= 0 && i
< strings::utils::getAlphabetCardinality())
685 std::vector
<unsigned> svec
= {i
.toUnsignedInt()};
686 results
[currNode
] = EvalResult(String(svec
));
690 results
[currNode
] = EvalResult(String(""));
695 case kind::STRING_TO_CODE
:
697 const String
& s
= results
[currNode
[0]].d_str
;
700 results
[currNode
] = EvalResult(Rational(s
.getVec()[0]));
704 results
[currNode
] = EvalResult(Rational(-1));
709 case kind::CONST_BITVECTOR
:
710 results
[currNode
] = EvalResult(currNodeVal
.getConst
<BitVector
>());
713 case kind::BITVECTOR_NOT
:
714 results
[currNode
] = EvalResult(~results
[currNode
[0]].d_bv
);
717 case kind::BITVECTOR_NEG
:
718 results
[currNode
] = EvalResult(-results
[currNode
[0]].d_bv
);
721 case kind::BITVECTOR_EXTRACT
:
723 unsigned lo
= bv::utils::getExtractLow(currNodeVal
);
724 unsigned hi
= bv::utils::getExtractHigh(currNodeVal
);
726 EvalResult(results
[currNode
[0]].d_bv
.extract(hi
, lo
));
730 case kind::BITVECTOR_CONCAT
:
732 BitVector res
= results
[currNode
[0]].d_bv
;
733 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
735 res
= res
.concat(results
[currNode
[i
]].d_bv
);
737 results
[currNode
] = EvalResult(res
);
741 case kind::BITVECTOR_PLUS
:
743 BitVector res
= results
[currNode
[0]].d_bv
;
744 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
746 res
= res
+ results
[currNode
[i
]].d_bv
;
748 results
[currNode
] = EvalResult(res
);
752 case kind::BITVECTOR_MULT
:
754 BitVector res
= results
[currNode
[0]].d_bv
;
755 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
757 res
= res
* results
[currNode
[i
]].d_bv
;
759 results
[currNode
] = EvalResult(res
);
762 case kind::BITVECTOR_AND
:
764 BitVector res
= results
[currNode
[0]].d_bv
;
765 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
767 res
= res
& results
[currNode
[i
]].d_bv
;
769 results
[currNode
] = EvalResult(res
);
773 case kind::BITVECTOR_OR
:
775 BitVector res
= results
[currNode
[0]].d_bv
;
776 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
778 res
= res
| results
[currNode
[i
]].d_bv
;
780 results
[currNode
] = EvalResult(res
);
784 case kind::BITVECTOR_XOR
:
786 BitVector res
= results
[currNode
[0]].d_bv
;
787 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
789 res
= res
^ results
[currNode
[i
]].d_bv
;
791 results
[currNode
] = EvalResult(res
);
794 case kind::BITVECTOR_UDIV
:
795 case kind::BITVECTOR_UDIV_TOTAL
:
797 if (currNodeVal
.getKind() == kind::BITVECTOR_UDIV_TOTAL
798 || results
[currNode
[1]].d_bv
.getValue() != 0)
800 BitVector res
= results
[currNode
[0]].d_bv
;
801 res
= res
.unsignedDivTotal(results
[currNode
[1]].d_bv
);
802 results
[currNode
] = EvalResult(res
);
806 results
[currNode
] = EvalResult();
807 evalAsNode
[currNode
] =
808 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
813 case kind::BITVECTOR_UREM
:
814 case kind::BITVECTOR_UREM_TOTAL
:
816 if (currNodeVal
.getKind() == kind::BITVECTOR_UREM_TOTAL
817 || results
[currNode
[1]].d_bv
.getValue() != 0)
819 BitVector res
= results
[currNode
[0]].d_bv
;
820 res
= res
.unsignedRemTotal(results
[currNode
[1]].d_bv
);
821 results
[currNode
] = EvalResult(res
);
825 results
[currNode
] = EvalResult();
826 evalAsNode
[currNode
] =
827 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
835 EvalResult lhs
= results
[currNode
[0]];
836 EvalResult rhs
= results
[currNode
[1]];
840 case EvalResult::BOOL
:
842 results
[currNode
] = EvalResult(lhs
.d_bool
== rhs
.d_bool
);
846 case EvalResult::BITVECTOR
:
848 results
[currNode
] = EvalResult(lhs
.d_bv
== rhs
.d_bv
);
852 case EvalResult::RATIONAL
:
854 results
[currNode
] = EvalResult(lhs
.d_rat
== rhs
.d_rat
);
858 case EvalResult::STRING
:
860 results
[currNode
] = EvalResult(lhs
.d_str
== rhs
.d_str
);
863 case EvalResult::UCONST
:
865 results
[currNode
] = EvalResult(lhs
.d_uc
== rhs
.d_uc
);
871 Trace("evaluator") << "Theory " << Theory::theoryOf(currNode
[0])
872 << " not supported" << std::endl
;
873 results
[currNode
] = EvalResult();
874 evalAsNode
[currNode
] =
875 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
886 if (results
[currNode
[0]].d_bool
)
888 results
[currNode
] = results
[currNode
[1]];
892 results
[currNode
] = results
[currNode
[2]];
899 Trace("evaluator") << "Kind " << currNodeVal
.getKind()
900 << " not supported" << std::endl
;
901 results
[currNode
] = EvalResult();
902 evalAsNode
[currNode
] =
903 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
913 Node
Evaluator::reconstruct(
915 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>& eresults
,
916 std::unordered_map
<TNode
, Node
, NodeHashFunction
>& evalAsNode
) const
918 if (n
.getNumChildren() == 0)
922 Trace("evaluator") << "Evaluator: reconstruct " << n
<< std::endl
;
923 NodeManager
* nm
= NodeManager::currentNM();
924 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>::iterator itr
;
925 std::unordered_map
<TNode
, Node
, NodeHashFunction
>::iterator itn
;
926 std::vector
<Node
> echildren
;
927 if (n
.getMetaKind() == kind::metakind::PARAMETERIZED
)
929 TNode op
= n
.getOperator();
932 echildren
.push_back(op
);
936 itr
= eresults
.find(op
);
937 Assert(itr
!= eresults
.end());
938 if (itr
->second
.d_tag
== EvalResult::INVALID
)
940 // could not evaluate the operator, look in the node cache
941 itn
= evalAsNode
.find(op
);
942 Assert(itn
!= evalAsNode
.end());
943 echildren
.push_back(itn
->second
);
947 // otherwise, use the evaluation of the operator
948 echildren
.push_back(itr
->second
.toNode());
952 for (const auto& currNodeChild
: n
)
954 itr
= eresults
.find(currNodeChild
);
955 Assert(itr
!= eresults
.end());
956 if (itr
->second
.d_tag
== EvalResult::INVALID
)
958 // could not evaluate this child, look in the node cache
959 itn
= evalAsNode
.find(currNodeChild
);
960 Assert(itn
!= evalAsNode
.end());
961 echildren
.push_back(itn
->second
);
965 // otherwise, use the evaluation
966 echildren
.push_back(itr
->second
.toNode());
969 // The value is the result of our (partially) successful evaluation
971 Node nn
= nm
->mkNode(n
.getKind(), echildren
);
972 Trace("evaluator") << "Evaluator: reconstructed " << nn
<< std::endl
;
973 // Return node, without rewriting. Notice we do not need to substitute here
974 // since all substitutions should already have been applied recursively.
978 } // namespace theory