Skip to content

Commit b74729f

Browse files
committed
adding comments
1 parent a464e5b commit b74729f

File tree

3 files changed

+138
-11
lines changed

3 files changed

+138
-11
lines changed

mathics/core/rules.py

Lines changed: 132 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ def function_arguments(f):
1919
return _python_function_arguments(f)
2020

2121

22+
class StopMatchConditionFailed(StopGenerator):
23+
pass
24+
25+
2226
class StopGenerator_BaseRule(StopGenerator):
2327
pass
2428

@@ -59,7 +63,11 @@ def yield_match(vars, rest):
5963
if name.startswith("_option_"):
6064
options[name[len("_option_") :]] = value
6165
del vars[name]
62-
new_expression = self.do_replace(expression, vars, options, evaluation)
66+
try:
67+
new_expression = self.do_replace(expression, vars, options, evaluation)
68+
except StopMatchConditionFailed:
69+
return
70+
6371
if new_expression is None:
6472
new_expression = expression
6573
if rest[0] or rest[1]:
@@ -107,7 +115,7 @@ def yield_match(vars, rest):
107115
def do_replace(self):
108116
raise NotImplementedError
109117

110-
def get_sort_key(self) -> tuple:
118+
def get_sort_key(self, pattern_sort=False) -> tuple:
111119
# FIXME: check if this makes sense:
112120
return tuple((self.system, self.pattern.get_sort_key(True)))
113121

@@ -131,20 +139,128 @@ class Rule(BaseRule):
131139
``G[1.^2, a^2]``
132140
"""
133141

142+
def __ge__(self, other):
143+
if isinstance(other, Rule):
144+
sys, key, rhs_cond = self.get_sort_key()
145+
sys_other, key_other, rhs_cond_other = other.get_sort_key()
146+
if sys != sys_other:
147+
return sys > sys_other
148+
if key != key_other:
149+
return key > key_other
150+
151+
# larger and more complex conditions come first
152+
len_cond, len_cond_other = len(rhs_cond), len(rhs_cond_other)
153+
if len_cond != len_cond_other:
154+
return len_cond_other > len_cond
155+
if len_cond == 0:
156+
return False
157+
for me_cond, other_cond in zip(rhs_cond, rhs_cond_other):
158+
me_sk = me_cond.get_sort_key(True)
159+
o_sk = other_cond.get_sort_key(True)
160+
if me_sk > o_sk:
161+
return False
162+
return True
163+
# Follow the usual rule
164+
return self.get_sort_key(True) >= other.get_sort_key(True)
165+
166+
def __gt__(self, other):
167+
if isinstance(other, Rule):
168+
sys, key, rhs_cond = self.get_sort_key()
169+
sys_other, key_other, rhs_cond_other = other.get_sort_key()
170+
if sys != sys_other:
171+
return sys > sys_other
172+
if key != key_other:
173+
return key > key_other
174+
175+
# larger and more complex conditions come first
176+
len_cond, len_cond_other = len(rhs_cond), len(rhs_cond_other)
177+
if len_cond != len_cond_other:
178+
return len_cond_other > len_cond
179+
if len_cond == 0:
180+
return False
181+
182+
for me_cond, other_cond in zip(rhs_cond, rhs_cond_other):
183+
me_sk = me_cond.get_sort_key(True)
184+
o_sk = other_cond.get_sort_key(True)
185+
if me_sk > o_sk:
186+
return False
187+
return me_sk > o_sk
188+
# Follow the usual rule
189+
return self.get_sort_key(True) > other.get_sort_key(True)
190+
191+
def __le__(self, other):
192+
if isinstance(other, Rule):
193+
sys, key, rhs_cond = self.get_sort_key()
194+
sys_other, key_other, rhs_cond_other = other.get_sort_key()
195+
if sys != sys_other:
196+
return sys < sys_other
197+
if key != key_other:
198+
return key < key_other
199+
200+
# larger and more complex conditions come first
201+
len_cond, len_cond_other = len(rhs_cond), len(rhs_cond_other)
202+
if len_cond != len_cond_other:
203+
return len_cond_other < len_cond
204+
if len_cond == 0:
205+
return False
206+
for me_cond, other_cond in zip(rhs_cond, rhs_cond_other):
207+
me_sk = me_cond.get_sort_key(True)
208+
o_sk = other_cond.get_sort_key(True)
209+
if me_sk < o_sk:
210+
return False
211+
return True
212+
# Follow the usual rule
213+
return self.get_sort_key(True) <= other.get_sort_key(True)
214+
215+
def __lt__(self, other):
216+
if isinstance(other, Rule):
217+
sys, key, rhs_cond = self.get_sort_key()
218+
sys_other, key_other, rhs_cond_other = other.get_sort_key()
219+
if sys != sys_other:
220+
return sys < sys_other
221+
if key != key_other:
222+
return key < key_other
223+
224+
# larger and more complex conditions come first
225+
len_cond, len_cond_other = len(rhs_cond), len(rhs_cond_other)
226+
if len_cond != len_cond_other:
227+
return len_cond_other < len_cond
228+
if len_cond == 0:
229+
return False
230+
231+
for me_cond, other_cond in zip(rhs_cond, rhs_cond_other):
232+
me_sk = me_cond.get_sort_key(True)
233+
o_sk = other_cond.get_sort_key(True)
234+
if me_sk < o_sk:
235+
return False
236+
return me_sk > o_sk
237+
# Follow the usual rule
238+
return self.get_sort_key(True) < other.get_sort_key(True)
239+
134240
def __init__(self, pattern, replace, delayed=True, system=False) -> None:
135241
super(Rule, self).__init__(pattern, system=system)
136242
self.replace = replace
137243
self.delayed = delayed
138-
139-
def do_replace(self, expression, vars, options, evaluation):
140-
replace = self.replace
141-
if self.delayed:
244+
# If delayed is True, and replace is a nested
245+
# Condition expression, stores the conditions and the
246+
# remaining stripped expression.
247+
# This is going to be used to compare and sort rules,
248+
# and also to decide if the rule matches an expression.
249+
conds = []
250+
if delayed:
142251
while replace.has_form("System`Condition", 2):
143252
replace, cond = replace.elements
144-
cond = cond.replace_vars(vars)
145-
cond = cond.evaluate(evaluation)
146-
if cond is not SymbolTrue:
147-
return None
253+
conds.append(cond)
254+
self.rhs_conditions = sorted(conds)
255+
self.strip_replace = replace
256+
257+
def do_replace(self, expression, vars, options, evaluation):
258+
replace = self.replace if self.rhs_conditions == [] else self.strip_replace
259+
for cond in self.rhs_conditions:
260+
cond = cond.replace_vars(vars)
261+
cond = cond.evaluate(evaluation)
262+
if cond is not SymbolTrue:
263+
raise StopMatchConditionFailed
148264

149265
new = replace.replace_vars(vars)
150266
new.options = options
@@ -169,6 +285,12 @@ def do_replace(self, expression, vars, options, evaluation):
169285
def __repr__(self) -> str:
170286
return "<Rule: %s -> %s>" % (self.pattern, self.replace)
171287

288+
def get_sort_key(self, pattern_sort=False) -> tuple:
289+
# FIXME: check if this makes sense:
290+
return tuple(
291+
(self.system, self.pattern.get_sort_key(True), self.rhs_conditions)
292+
)
293+
172294

173295
class BuiltinRule(BaseRule):
174296
"""

mathics/core/systemsymbols.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@
169169
SymbolSeries = Symbol("System`Series")
170170
SymbolSeriesData = Symbol("System`SeriesData")
171171
SymbolSet = Symbol("System`Set")
172+
SymbolSetDelayed = Symbol("System`SetDelayed")
172173
SymbolSign = Symbol("System`Sign")
173174
SymbolSimplify = Symbol("System`Simplify")
174175
SymbolSin = Symbol("System`Sin")
@@ -186,6 +187,8 @@
186187
SymbolSubsuperscriptBox = Symbol("System`SubsuperscriptBox")
187188
SymbolSuperscriptBox = Symbol("System`SuperscriptBox")
188189
SymbolTable = Symbol("System`Table")
190+
SymbolTagSet = Symbol("System`TagSet")
191+
SymbolTagSetDelayed = Symbol("System`TagSetDelayed")
189192
SymbolTeXForm = Symbol("System`TeXForm")
190193
SymbolThrow = Symbol("System`Throw")
191194
SymbolToString = Symbol("System`ToString")
@@ -194,5 +197,7 @@
194197
SymbolUndefined = Symbol("System`Undefined")
195198
SymbolUnequal = Symbol("System`Unequal")
196199
SymbolUnevaluated = Symbol("System`Unevaluated")
200+
SymbolUpSet = Symbol("System`UpSet")
201+
SymbolUpSetDelayed = Symbol("System`UpSetDelayed")
197202
SymbolUpValues = Symbol("System`UpValues")
198203
SymbolXor = Symbol("System`Xor")

test/test_control.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def test_condition():
6969
evaluate(
7070
"""
7171
(* Define a function that can "throw an exception": *)
72-
72+
ClearAll[f];
7373
f[x_] := ppp[x]/; x>0
7474
"""
7575
)

0 commit comments

Comments
 (0)