(self, old, new, _seen)
| 605 | return self._substitute(old, new, _seen=set()) |
| 606 | |
| 607 | def _substitute(self, old, new, _seen): |
| 608 | if self._name in _seen: |
| 609 | return self |
| 610 | # Check if we are replacing a literal |
| 611 | if isinstance(old, Expr): |
| 612 | substitute_literal = False |
| 613 | if self._name == old._name: |
| 614 | return new |
| 615 | else: |
| 616 | substitute_literal = True |
| 617 | if isinstance(old, bool): |
| 618 | raise TypeError("Arguments to `substitute` cannot be bool.") |
| 619 | |
| 620 | new_exprs = [] |
| 621 | update = False |
| 622 | for operand in self.operands: |
| 623 | if isinstance(operand, Expr): |
| 624 | val = operand._substitute(old, new, _seen) |
| 625 | if operand._name != val._name: |
| 626 | update = True |
| 627 | new_exprs.append(val) |
| 628 | elif ( |
| 629 | "Fused" in type(self).__name__ |
| 630 | and isinstance(operand, list) |
| 631 | and all(isinstance(op, Expr) for op in operand) |
| 632 | ): |
| 633 | # Special handling for `Fused`. |
| 634 | # We make no promise to dive through a |
| 635 | # list operand in general, but NEED to |
| 636 | # do so for the `Fused.exprs` operand. |
| 637 | val = [] |
| 638 | for op in operand: |
| 639 | val.append(op._substitute(old, new, _seen)) |
| 640 | if val[-1]._name != op._name: |
| 641 | update = True |
| 642 | new_exprs.append(val) |
| 643 | elif ( |
| 644 | substitute_literal |
| 645 | and not isinstance(operand, bool) |
| 646 | and isinstance(operand, type(old)) |
| 647 | and operand == old |
| 648 | ): |
| 649 | new_exprs.append(new) |
| 650 | update = True |
| 651 | else: |
| 652 | new_exprs.append(operand) |
| 653 | |
| 654 | if update: # Only recreate if something changed |
| 655 | return type(self)(*new_exprs) |
| 656 | else: |
| 657 | _seen.add(self._name) |
| 658 | return self |
| 659 | |
| 660 | def substitute_parameters(self, substitutions: dict) -> Expr: |
| 661 | """Substitute specific `Expr` parameters |
no test coverage detected