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;
214 if (currNode
.getMetaKind() == kind::metakind::PARAMETERIZED
)
216 TNode op
= currNode
.getOperator();
217 // Certain nodes are parameterized with constant operators, including
218 // bitvector extract. These operators do not need to be evaluated.
221 itr
= results
.find(op
);
222 if (itr
== results
.end())
224 queue
.emplace_back(op
);
227 else if (itr
->second
.d_tag
== EvalResult::INVALID
)
233 for (const auto& currNodeChild
: currNode
)
235 itr
= results
.find(currNodeChild
);
236 if (itr
== results
.end())
238 queue
.emplace_back(currNodeChild
);
241 else if (itr
->second
.d_tag
== EvalResult::INVALID
)
243 // we cannot evaluate since there was an invalid child
247 Trace("evaluator") << "Evaluator: visit " << currNode
248 << ", process = " << doProcess
249 << ", evaluate = " << doEval
<< std::endl
;
255 Node currNodeVal
= currNode
;
256 // whether we need to reconstruct the current node in the case of failure
257 bool needsReconstruct
= true;
259 // The code below should either:
260 // (1) store a valid EvalResult into results[currNode], or
261 // (2) store an invalid EvalResult into results[currNode] and
262 // store the result of substitution + rewriting currNode { args -> vals }
263 // into evalAsNode[currNode].
265 // If we did not successfully evaluate all children
268 // Reconstruct the node with a combination of the children that
269 // successfully evaluated, and the children that did not.
270 Trace("evaluator") << "Evaluator: collect arguments" << std::endl
;
271 currNodeVal
= reconstruct(currNodeVal
, results
, evalAsNode
);
274 // Rewrite the result now, if we use the rewriter. We will see below
275 // if we are able to turn it into a valid EvalResult.
276 currNodeVal
= Rewriter::rewrite(currNodeVal
);
278 needsReconstruct
= false;
279 Trace("evaluator") << "Evaluator: now after substitution + rewriting: "
280 << currNodeVal
<< std::endl
;
281 if (currNodeVal
.getNumChildren() > 0)
283 // We may continue with a valid EvalResult at this point only if
284 // we have no children. We must otherwise fail here since some of
285 // our children may not have successful evaluations.
286 results
[currNode
] = EvalResult();
287 evalAsNode
[currNode
] = currNodeVal
;
290 // Otherwise, we may be able to turn the overall result into an
291 // valid EvalResult and continue. We fallthrough and continue with the
292 // block of code below.
295 if (currNode
.isVar())
297 const auto& it
= std::find(args
.begin(), args
.end(), currNode
);
298 if (it
== args
.end())
300 // variable with no substitution is itself
301 evalAsNode
[currNode
] = currNode
;
302 results
[currNode
] = EvalResult();
305 ptrdiff_t pos
= std::distance(args
.begin(), it
);
306 currNodeVal
= vals
[pos
];
307 // Don't need to reconstruct since range of substitution should already
309 needsReconstruct
= false;
311 else if (currNode
.getKind() == kind::APPLY_UF
)
313 Trace("evaluator") << "Evaluate " << currNode
<< std::endl
;
314 TNode op
= currNode
.getOperator();
315 Assert(evalAsNode
.find(op
) != evalAsNode
.end());
316 // no function can be a valid EvalResult
318 Trace("evaluator") << "Operator evaluated to " << op
<< std::endl
;
319 if (op
.getKind() != kind::LAMBDA
)
321 // this node is not evaluatable due to operator, must add to
323 results
[currNode
] = EvalResult();
324 evalAsNode
[currNode
] = reconstruct(currNode
, results
, evalAsNode
);
327 // Create a copy of the current substitutions
328 std::vector
<Node
> lambdaArgs(args
);
329 std::vector
<Node
> lambdaVals(vals
);
331 // Add the values for the arguments of the lambda as substitutions at
332 // the beginning of the vector to shadow variables from outer scopes
333 // with the same name
334 for (const auto& lambdaArg
: op
[0])
336 lambdaArgs
.insert(lambdaArgs
.begin(), lambdaArg
);
339 for (const auto& lambdaVal
: currNode
)
341 lambdaVals
.insert(lambdaVals
.begin(), results
[lambdaVal
].toNode());
344 // Lambdas are evaluated in a recursive fashion because each evaluation
345 // requires different substitutions. We use a fresh cache since the
346 // evaluation of op[1] is under a new substitution and thus should not
347 // be cached. We could alternatively copy evalAsNode to evalAsNodeC but
348 // favor avoiding this copy for performance reasons.
349 std::unordered_map
<TNode
, Node
, NodeHashFunction
> evalAsNodeC
;
350 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
> resultsC
;
352 evalInternal(op
[1], lambdaArgs
, lambdaVals
, evalAsNodeC
, resultsC
, useRewriter
);
353 Trace("evaluator") << "Evaluated via arguments to "
354 << results
[currNode
].d_tag
<< std::endl
;
355 if (results
[currNode
].d_tag
== EvalResult::INVALID
)
357 // evaluation was invalid, we take the node of op[1] as the result
358 evalAsNode
[currNode
] = evalAsNodeC
[op
[1]];
360 << "Take node evaluation: " << evalAsNodeC
[op
[1]] << std::endl
;
365 switch (currNodeVal
.getKind())
367 case kind::CONST_BOOLEAN
:
368 results
[currNode
] = EvalResult(currNodeVal
.getConst
<bool>());
373 results
[currNode
] = EvalResult(!(results
[currNode
[0]].d_bool
));
379 bool res
= results
[currNode
[0]].d_bool
;
380 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
382 res
= res
&& results
[currNode
[i
]].d_bool
;
384 results
[currNode
] = EvalResult(res
);
390 bool res
= results
[currNode
[0]].d_bool
;
391 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
393 res
= res
|| results
[currNode
[i
]].d_bool
;
395 results
[currNode
] = EvalResult(res
);
399 case kind::CONST_RATIONAL
:
401 const Rational
& r
= currNodeVal
.getConst
<Rational
>();
402 results
[currNode
] = EvalResult(r
);
405 case kind::UNINTERPRETED_CONSTANT
:
407 const UninterpretedConstant
& uc
=
408 currNodeVal
.getConst
<UninterpretedConstant
>();
409 results
[currNode
] = EvalResult(uc
);
414 Rational res
= results
[currNode
[0]].d_rat
;
415 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
417 res
= res
+ results
[currNode
[i
]].d_rat
;
419 results
[currNode
] = EvalResult(res
);
425 const Rational
& x
= results
[currNode
[0]].d_rat
;
426 const Rational
& y
= results
[currNode
[1]].d_rat
;
427 results
[currNode
] = EvalResult(x
- y
);
433 const Rational
& x
= results
[currNode
[0]].d_rat
;
434 results
[currNode
] = EvalResult(-x
);
438 case kind::NONLINEAR_MULT
:
440 Rational res
= results
[currNode
[0]].d_rat
;
441 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
443 res
= res
* results
[currNode
[i
]].d_rat
;
445 results
[currNode
] = EvalResult(res
);
451 const Rational
& x
= results
[currNode
[0]].d_rat
;
452 const Rational
& y
= results
[currNode
[1]].d_rat
;
453 results
[currNode
] = EvalResult(x
>= y
);
458 const Rational
& x
= results
[currNode
[0]].d_rat
;
459 const Rational
& y
= results
[currNode
[1]].d_rat
;
460 results
[currNode
] = EvalResult(x
<= y
);
465 const Rational
& x
= results
[currNode
[0]].d_rat
;
466 const Rational
& y
= results
[currNode
[1]].d_rat
;
467 results
[currNode
] = EvalResult(x
> y
);
472 const Rational
& x
= results
[currNode
[0]].d_rat
;
473 const Rational
& y
= results
[currNode
[1]].d_rat
;
474 results
[currNode
] = EvalResult(x
< y
);
479 const Rational
& x
= results
[currNode
[0]].d_rat
;
480 results
[currNode
] = EvalResult(x
.abs());
483 case kind::CONST_STRING
:
484 results
[currNode
] = EvalResult(currNodeVal
.getConst
<String
>());
487 case kind::STRING_CONCAT
:
489 String res
= results
[currNode
[0]].d_str
;
490 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
492 res
= res
.concat(results
[currNode
[i
]].d_str
);
494 results
[currNode
] = EvalResult(res
);
498 case kind::STRING_LENGTH
:
500 const String
& s
= results
[currNode
[0]].d_str
;
501 results
[currNode
] = EvalResult(Rational(s
.size()));
505 case kind::STRING_SUBSTR
:
507 const String
& s
= results
[currNode
[0]].d_str
;
508 Integer
s_len(s
.size());
509 Integer i
= results
[currNode
[1]].d_rat
.getNumerator();
510 Integer j
= results
[currNode
[2]].d_rat
.getNumerator();
512 if (i
.strictlyNegative() || j
.strictlyNegative() || i
>= s_len
)
514 results
[currNode
] = EvalResult(String(""));
516 else if (i
+ j
> s_len
)
519 EvalResult(s
.suffix((s_len
- i
).toUnsignedInt()));
524 EvalResult(s
.substr(i
.toUnsignedInt(), j
.toUnsignedInt()));
529 case kind::STRING_UPDATE
:
531 const String
& s
= results
[currNode
[0]].d_str
;
532 Integer
s_len(s
.size());
533 Integer i
= results
[currNode
[1]].d_rat
.getNumerator();
534 const String
& t
= results
[currNode
[2]].d_str
;
536 if (i
.strictlyNegative() || i
>= s_len
)
538 results
[currNode
] = EvalResult(s
);
542 results
[currNode
] = EvalResult(s
.update(i
.toUnsignedInt(), t
));
546 case kind::STRING_CHARAT
:
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 if (i
.strictlyNegative() || i
>= s_len
)
553 results
[currNode
] = EvalResult(String(""));
557 results
[currNode
] = EvalResult(s
.substr(i
.toUnsignedInt(), 1));
562 case kind::STRING_STRCTN
:
564 const String
& s
= results
[currNode
[0]].d_str
;
565 const String
& t
= results
[currNode
[1]].d_str
;
566 results
[currNode
] = EvalResult(s
.find(t
) != std::string::npos
);
570 case kind::STRING_STRIDOF
:
572 const String
& s
= results
[currNode
[0]].d_str
;
573 Integer
s_len(s
.size());
574 const String
& x
= results
[currNode
[1]].d_str
;
575 Integer i
= results
[currNode
[2]].d_rat
.getNumerator();
577 if (i
.strictlyNegative())
579 results
[currNode
] = EvalResult(Rational(-1));
583 size_t r
= s
.find(x
, i
.toUnsignedInt());
584 if (r
== std::string::npos
)
586 results
[currNode
] = EvalResult(Rational(-1));
590 results
[currNode
] = EvalResult(Rational(r
));
596 case kind::STRING_STRREPL
:
598 const String
& s
= results
[currNode
[0]].d_str
;
599 const String
& x
= results
[currNode
[1]].d_str
;
600 const String
& y
= results
[currNode
[2]].d_str
;
601 results
[currNode
] = EvalResult(s
.replace(x
, y
));
605 case kind::STRING_PREFIX
:
607 const String
& t
= results
[currNode
[0]].d_str
;
608 const String
& s
= results
[currNode
[1]].d_str
;
609 if (s
.size() < t
.size())
611 results
[currNode
] = EvalResult(false);
615 results
[currNode
] = EvalResult(s
.prefix(t
.size()) == t
);
620 case kind::STRING_SUFFIX
:
622 const String
& t
= results
[currNode
[0]].d_str
;
623 const String
& s
= results
[currNode
[1]].d_str
;
624 if (s
.size() < t
.size())
626 results
[currNode
] = EvalResult(false);
630 results
[currNode
] = EvalResult(s
.suffix(t
.size()) == t
);
635 case kind::STRING_ITOS
:
637 Integer i
= results
[currNode
[0]].d_rat
.getNumerator();
638 if (i
.strictlyNegative())
640 results
[currNode
] = EvalResult(String(""));
644 results
[currNode
] = EvalResult(String(i
.toString()));
649 case kind::STRING_STOI
:
651 const String
& s
= results
[currNode
[0]].d_str
;
654 results
[currNode
] = EvalResult(Rational(s
.toNumber()));
658 results
[currNode
] = EvalResult(Rational(-1));
663 case kind::STRING_FROM_CODE
:
665 Integer i
= results
[currNode
[0]].d_rat
.getNumerator();
666 if (i
>= 0 && i
< strings::utils::getAlphabetCardinality())
668 std::vector
<unsigned> svec
= {i
.toUnsignedInt()};
669 results
[currNode
] = EvalResult(String(svec
));
673 results
[currNode
] = EvalResult(String(""));
678 case kind::STRING_TO_CODE
:
680 const String
& s
= results
[currNode
[0]].d_str
;
683 results
[currNode
] = EvalResult(Rational(s
.getVec()[0]));
687 results
[currNode
] = EvalResult(Rational(-1));
692 case kind::CONST_BITVECTOR
:
693 results
[currNode
] = EvalResult(currNodeVal
.getConst
<BitVector
>());
696 case kind::BITVECTOR_NOT
:
697 results
[currNode
] = EvalResult(~results
[currNode
[0]].d_bv
);
700 case kind::BITVECTOR_NEG
:
701 results
[currNode
] = EvalResult(-results
[currNode
[0]].d_bv
);
704 case kind::BITVECTOR_EXTRACT
:
706 unsigned lo
= bv::utils::getExtractLow(currNodeVal
);
707 unsigned hi
= bv::utils::getExtractHigh(currNodeVal
);
709 EvalResult(results
[currNode
[0]].d_bv
.extract(hi
, lo
));
713 case kind::BITVECTOR_CONCAT
:
715 BitVector res
= results
[currNode
[0]].d_bv
;
716 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
718 res
= res
.concat(results
[currNode
[i
]].d_bv
);
720 results
[currNode
] = EvalResult(res
);
724 case kind::BITVECTOR_PLUS
:
726 BitVector res
= results
[currNode
[0]].d_bv
;
727 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
729 res
= res
+ results
[currNode
[i
]].d_bv
;
731 results
[currNode
] = EvalResult(res
);
735 case kind::BITVECTOR_MULT
:
737 BitVector res
= results
[currNode
[0]].d_bv
;
738 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
740 res
= res
* results
[currNode
[i
]].d_bv
;
742 results
[currNode
] = EvalResult(res
);
745 case kind::BITVECTOR_AND
:
747 BitVector res
= results
[currNode
[0]].d_bv
;
748 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
750 res
= res
& results
[currNode
[i
]].d_bv
;
752 results
[currNode
] = EvalResult(res
);
756 case kind::BITVECTOR_OR
:
758 BitVector res
= results
[currNode
[0]].d_bv
;
759 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
761 res
= res
| results
[currNode
[i
]].d_bv
;
763 results
[currNode
] = EvalResult(res
);
767 case kind::BITVECTOR_XOR
:
769 BitVector res
= results
[currNode
[0]].d_bv
;
770 for (size_t i
= 1, end
= currNode
.getNumChildren(); i
< end
; i
++)
772 res
= res
^ results
[currNode
[i
]].d_bv
;
774 results
[currNode
] = EvalResult(res
);
777 case kind::BITVECTOR_UDIV
:
778 case kind::BITVECTOR_UDIV_TOTAL
:
780 if (currNodeVal
.getKind() == kind::BITVECTOR_UDIV_TOTAL
781 || results
[currNode
[1]].d_bv
.getValue() != 0)
783 BitVector res
= results
[currNode
[0]].d_bv
;
784 res
= res
.unsignedDivTotal(results
[currNode
[1]].d_bv
);
785 results
[currNode
] = EvalResult(res
);
789 results
[currNode
] = EvalResult();
790 evalAsNode
[currNode
] =
791 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
796 case kind::BITVECTOR_UREM
:
797 case kind::BITVECTOR_UREM_TOTAL
:
799 if (currNodeVal
.getKind() == kind::BITVECTOR_UREM_TOTAL
800 || results
[currNode
[1]].d_bv
.getValue() != 0)
802 BitVector res
= results
[currNode
[0]].d_bv
;
803 res
= res
.unsignedRemTotal(results
[currNode
[1]].d_bv
);
804 results
[currNode
] = EvalResult(res
);
808 results
[currNode
] = EvalResult();
809 evalAsNode
[currNode
] =
810 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
818 EvalResult lhs
= results
[currNode
[0]];
819 EvalResult rhs
= results
[currNode
[1]];
823 case EvalResult::BOOL
:
825 results
[currNode
] = EvalResult(lhs
.d_bool
== rhs
.d_bool
);
829 case EvalResult::BITVECTOR
:
831 results
[currNode
] = EvalResult(lhs
.d_bv
== rhs
.d_bv
);
835 case EvalResult::RATIONAL
:
837 results
[currNode
] = EvalResult(lhs
.d_rat
== rhs
.d_rat
);
841 case EvalResult::STRING
:
843 results
[currNode
] = EvalResult(lhs
.d_str
== rhs
.d_str
);
846 case EvalResult::UCONST
:
848 results
[currNode
] = EvalResult(lhs
.d_uc
== rhs
.d_uc
);
854 Trace("evaluator") << "Theory " << Theory::theoryOf(currNode
[0])
855 << " not supported" << std::endl
;
856 results
[currNode
] = EvalResult();
857 evalAsNode
[currNode
] =
858 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
869 if (results
[currNode
[0]].d_bool
)
871 results
[currNode
] = results
[currNode
[1]];
875 results
[currNode
] = results
[currNode
[2]];
882 Trace("evaluator") << "Kind " << currNodeVal
.getKind()
883 << " not supported" << std::endl
;
884 results
[currNode
] = EvalResult();
885 evalAsNode
[currNode
] =
886 needsReconstruct
? reconstruct(currNode
, results
, evalAsNode
)
896 Node
Evaluator::reconstruct(
898 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>& eresults
,
899 std::unordered_map
<TNode
, Node
, NodeHashFunction
>& evalAsNode
) const
901 if (n
.getNumChildren() == 0)
905 Trace("evaluator") << "Evaluator: reconstruct " << n
<< std::endl
;
906 NodeManager
* nm
= NodeManager::currentNM();
907 std::unordered_map
<TNode
, EvalResult
, TNodeHashFunction
>::iterator itr
;
908 std::unordered_map
<TNode
, Node
, NodeHashFunction
>::iterator itn
;
909 std::vector
<Node
> echildren
;
910 if (n
.getMetaKind() == kind::metakind::PARAMETERIZED
)
912 TNode op
= n
.getOperator();
915 echildren
.push_back(op
);
919 itr
= eresults
.find(op
);
920 Assert(itr
!= eresults
.end());
921 if (itr
->second
.d_tag
== EvalResult::INVALID
)
923 // could not evaluate the operator, look in the node cache
924 itn
= evalAsNode
.find(op
);
925 Assert(itn
!= evalAsNode
.end());
926 echildren
.push_back(itn
->second
);
930 // otherwise, use the evaluation of the operator
931 echildren
.push_back(itr
->second
.toNode());
935 for (const auto& currNodeChild
: n
)
937 itr
= eresults
.find(currNodeChild
);
938 Assert(itr
!= eresults
.end());
939 if (itr
->second
.d_tag
== EvalResult::INVALID
)
941 // could not evaluate this child, look in the node cache
942 itn
= evalAsNode
.find(currNodeChild
);
943 Assert(itn
!= evalAsNode
.end());
944 echildren
.push_back(itn
->second
);
948 // otherwise, use the evaluation
949 echildren
.push_back(itr
->second
.toNode());
952 // The value is the result of our (partially) successful evaluation
954 Node nn
= nm
->mkNode(n
.getKind(), echildren
);
955 Trace("evaluator") << "Evaluator: reconstructed " << nn
<< std::endl
;
956 // Return node, without rewriting. Notice we do not need to substitute here
957 // since all substitutions should already have been applied recursively.
961 } // namespace theory