5
5
6
6
from mathics .core .element import KeyComparable
7
7
from mathics .core .expression import Expression
8
- from mathics .core .symbols import strip_context
8
+ from mathics .core .symbols import strip_context , SymbolTrue
9
9
from mathics .core .pattern import Pattern , StopGenerator
10
10
11
11
from itertools import chain
@@ -19,6 +19,10 @@ def function_arguments(f):
19
19
return _python_function_arguments (f )
20
20
21
21
22
+ class StopMatchConditionFailed (StopGenerator ):
23
+ pass
24
+
25
+
22
26
class StopGenerator_BaseRule (StopGenerator ):
23
27
pass
24
28
@@ -59,7 +63,11 @@ def yield_match(vars, rest):
59
63
if name .startswith ("_option_" ):
60
64
options [name [len ("_option_" ) :]] = value
61
65
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
+
63
71
if new_expression is None :
64
72
new_expression = expression
65
73
if rest [0 ] or rest [1 ]:
@@ -107,7 +115,7 @@ def yield_match(vars, rest):
107
115
def do_replace (self ):
108
116
raise NotImplementedError
109
117
110
- def get_sort_key (self ) -> tuple :
118
+ def get_sort_key (self , pattern_sort = False ) -> tuple :
111
119
# FIXME: check if this makes sense:
112
120
return tuple ((self .system , self .pattern .get_sort_key (True )))
113
121
@@ -131,12 +139,131 @@ class Rule(BaseRule):
131
139
``G[1.^2, a^2]``
132
140
"""
133
141
134
- def __init__ (self , pattern , replace , system = False ) -> None :
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
+
240
+ def __init__ (self , pattern , replace , delayed = True , system = False ) -> None :
135
241
super (Rule , self ).__init__ (pattern , system = system )
136
242
self .replace = replace
243
+ self .delayed = 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 :
251
+ while replace .has_form ("System`Condition" , 2 ):
252
+ replace , cond = replace .elements
253
+ conds .append (cond )
254
+
255
+ self .rhs_conditions = sorted (conds )
256
+ self .strip_replace = replace
137
257
138
258
def do_replace (self , expression , vars , options , evaluation ):
139
- new = self .replace .replace_vars (vars )
259
+ replace = self .replace if self .rhs_conditions == [] else self .strip_replace
260
+ for cond in self .rhs_conditions :
261
+ cond = cond .replace_vars (vars )
262
+ cond = cond .evaluate (evaluation )
263
+ if cond is not SymbolTrue :
264
+ raise StopMatchConditionFailed
265
+
266
+ new = replace .replace_vars (vars )
140
267
new .options = options
141
268
142
269
# if options is a non-empty dict, we need to ensure reevaluation of the whole expression, since 'new' will
@@ -159,6 +286,12 @@ def do_replace(self, expression, vars, options, evaluation):
159
286
def __repr__ (self ) -> str :
160
287
return "<Rule: %s -> %s>" % (self .pattern , self .replace )
161
288
289
+ def get_sort_key (self , pattern_sort = False ) -> tuple :
290
+ # FIXME: check if this makes sense:
291
+ return tuple (
292
+ (self .system , self .pattern .get_sort_key (True ), self .rhs_conditions )
293
+ )
294
+
162
295
163
296
class BuiltinRule (BaseRule ):
164
297
"""
0 commit comments