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