Skip to content

Commit 0c49791

Browse files
committed
fix do_replace in rules where the replacement expression consists on a (nested) Condition[expr, pat] expression
1 parent 2ffdf02 commit 0c49791

File tree

3 files changed

+25
-3
lines changed

3 files changed

+25
-3
lines changed

CHANGES.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ Bugs
5050

5151
# ``0`` with a given precision (like in ```0`3```) is now parsed as ``0``, an integer number.
5252
#. ``RandomSample`` with one list argument now returns a random ordering of the list items. Previously it would return just one item.
53-
53+
#. Rules of the form ``pat->Condition[expr, cond]`` are handled as in WL. The same works for nested `Condition` expressions.
5454

5555
Enhancements
5656
++++++++++++

mathics/core/rules.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
from mathics.core.element import KeyComparable
77
from mathics.core.expression import Expression
8-
from mathics.core.symbols import strip_context
8+
from mathics.core.symbols import strip_context, SymbolTrue
99
from mathics.core.pattern import Pattern, StopGenerator
1010

1111
from itertools import chain
@@ -136,7 +136,15 @@ def __init__(self, pattern, replace, system=False) -> None:
136136
self.replace = replace
137137

138138
def do_replace(self, expression, vars, options, evaluation):
139-
new = self.replace.replace_vars(vars)
139+
replace = self.replace
140+
while replace.has_form("System`Condition", 2):
141+
replace, cond = replace.elements
142+
cond = cond.replace_vars(vars)
143+
cond = cond.evaluate(evaluation)
144+
if cond is not SymbolTrue:
145+
return None
146+
147+
new = replace.replace_vars(vars)
140148
new.options = options
141149

142150
# if options is a non-empty dict, we need to ensure reevaluation of the whole expression, since 'new' will

test/builtin/test_patterns.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,17 @@ def test_replace_all():
2626
),
2727
):
2828
check_evaluation(str_expr, str_expected, message)
29+
30+
31+
def test_rule_repl_cond():
32+
for str_expr, str_expected, message in (
33+
("f[x]/.(f[u_]->u^2/; u>3/; u>2)", "f[x]", "conditions are not evaluated"),
34+
("f[4]/.(f[u_]->u^2/; u>3/; u>2)", "16", "both conditions are True"),
35+
(
36+
"f[2.5]/.(f[u_]->u^2/; u>3/; u>2)",
37+
"f[2.5]",
38+
"just the first condition is True",
39+
),
40+
("f[1.]/.(f[u_]->u^2/; u>3/; u>2)", "f[1.]", "Both conditions are False"),
41+
):
42+
check_evaluation(str_expr, str_expected, message)

0 commit comments

Comments
 (0)