| 532 | }; |
| 533 | |
| 534 | void inlineLetExpressions(SMTLib2Expression& _expr, LetBindings& _bindings) |
| 535 | { |
| 536 | if (isAtom(_expr)) |
| 537 | { |
| 538 | auto const& atom = asAtom(_expr); |
| 539 | if (_bindings.has(atom)) |
| 540 | _expr = _bindings[atom]; |
| 541 | return; |
| 542 | } |
| 543 | auto& subexprs = asSubExpressions(_expr); |
| 544 | smtSolverInteractionRequire(!subexprs.empty(), "Invalid let expression"); |
| 545 | auto const& first = subexprs.at(0); |
| 546 | if (isAtom(first) && asAtom(first) == "let") |
| 547 | { |
| 548 | smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); |
| 549 | smtSolverInteractionRequire(!isAtom(subexprs[1]), "Invalid let expression"); |
| 550 | auto& bindingExpressions = asSubExpressions(subexprs[1]); |
| 551 | // process new bindings |
| 552 | std::vector<std::pair<std::string, SMTLib2Expression>> newBindings; |
| 553 | for (auto& binding: bindingExpressions) |
| 554 | { |
| 555 | smtSolverInteractionRequire(!isAtom(binding), "Invalid let expression"); |
| 556 | auto& bindingPair = asSubExpressions(binding); |
| 557 | smtSolverInteractionRequire(bindingPair.size() == 2, "Invalid let expression"); |
| 558 | smtSolverInteractionRequire(isAtom(bindingPair.at(0)), "Invalid let expression"); |
| 559 | inlineLetExpressions(bindingPair.at(1), _bindings); |
| 560 | newBindings.emplace_back(asAtom(bindingPair.at(0)), bindingPair.at(1)); |
| 561 | } |
| 562 | _bindings.pushScope(); |
| 563 | for (auto&& [name, expr]: newBindings) |
| 564 | _bindings.addBinding(std::move(name), std::move(expr)); |
| 565 | |
| 566 | newBindings.clear(); |
| 567 | |
| 568 | // get new subexpression |
| 569 | inlineLetExpressions(subexprs.at(2), _bindings); |
| 570 | // remove the new bindings |
| 571 | _bindings.popScope(); |
| 572 | |
| 573 | // update the expression |
| 574 | auto tmp = std::move(subexprs.at(2)); |
| 575 | _expr = std::move(tmp); |
| 576 | return; |
| 577 | } |
| 578 | else if (isAtom(first) && (asAtom(first) == "forall" || asAtom(first) == "exists")) |
| 579 | { |
| 580 | // A little hack to ensure quantified variables are not substituted because of some outer let definition: |
| 581 | // We define the current binding of the variable to itself, before we recurse in to subterm |
| 582 | smtSolverInteractionRequire(subexprs.size() == 3, "Invalid let expression"); |
| 583 | _bindings.pushScope(); |
| 584 | for (auto const& sortedVar: asSubExpressions(subexprs.at(1))) |
| 585 | { |
| 586 | auto const& varNameExpr = asSubExpressions(sortedVar).at(0); |
| 587 | _bindings.addBinding(asAtom(varNameExpr), varNameExpr); |
| 588 | } |
| 589 | inlineLetExpressions(subexprs.at(2), _bindings); |
| 590 | _bindings.popScope(); |
| 591 | return; |
no test coverage detected