@@ -602,10 +602,13 @@ def subs(self, substitutions, default=None, simplify=False):
602
602
603
603
Note that this can be used to tested for expression containment.
604
604
"""
605
+ # shortcut: check if we have our whole expression as a possible
606
+ # subsitution source
605
607
for expr , substitution in substitutions .items ():
606
608
if expr == self :
607
609
return substitution
608
610
611
+ # otherwise, do a proper substitution of sub expressions
609
612
expr = self ._subs (substitutions , default , simplify )
610
613
return self if expr is None else expr
611
614
@@ -615,34 +618,53 @@ def _subs(self, substitutions, default, simplify):
615
618
substituted by the corresponding value expression using a mapping of:
616
619
{expr->expr to substitute.}
617
620
"""
618
- new_args = []
621
+ # track the new list of unchanged args or replaced args through
622
+ # a substitution
623
+ new_arguments = []
619
624
changed_something = False
620
625
626
+ # shortcut for basic logic True or False
621
627
if self is self .TRUE or self is self .FALSE :
622
628
return self
623
629
630
+ # if the expression has no elements, e.g. is empty, do not apply
631
+ # substitions
624
632
if not self .args :
625
633
return default
626
634
635
+ # iterate the subexpressions: either plain symbols or a subexpressions
627
636
for arg in self .args :
637
+ # collect substitutions for exact matches
638
+ # break as soon as we have a match
628
639
for expr , substitution in substitutions .items ():
629
640
if arg == expr :
630
- new_args .append (substitution )
641
+ new_arguments .append (substitution )
631
642
changed_something = True
632
643
break
644
+
645
+ # this will execute only if we did not break out of the
646
+ # loop, e.g. if we did not change anything and did not
647
+ # collect any substitutions
633
648
else :
649
+ # recursively call _subs on each arg to see if we get a
650
+ # substituted arg
634
651
new_arg = arg ._subs (substitutions , default , simplify )
635
652
if new_arg is None :
636
- new_args .append (arg )
653
+ # if we did not collect a substitution for this arg,
654
+ # keep the arg as-is, it is not replaced by anything
655
+ new_arguments .append (arg )
637
656
else :
638
- new_args .append (new_arg )
657
+ # otherwise, we add the substitution for this arg instead
658
+ new_arguments .append (new_arg )
639
659
changed_something = True
640
660
641
- if changed_something :
642
- newexpr = self .__class__ (* new_args )
643
- if simplify :
644
- newexpr = newexpr .simplify ()
645
- return newexpr
661
+ if not changed_something :
662
+ return
663
+
664
+ # here we did some substitution: we return a new expression
665
+ # built from the new_arguments
666
+ newexpr = self .__class__ (* new_arguments )
667
+ return newexpr .simplify () if simplify else newexpr
646
668
647
669
def simplify (self ):
648
670
"""
0 commit comments