1919 BLANKSEQUENCE_GENERAL_PATTERN_SORT_KEY ,
2020 BLANKSEQUENCE_WITH_PATTERN_PATTERN_SORT_KEY ,
2121)
22- from mathics .core .symbols import BaseElement
22+ from mathics .core .symbols import BaseElement , Symbol
2323
2424# This tells documentation how to sort this module
2525sort_order = "mathics.builtin.rules-and-patterns.basic"
2626
2727
2828class _Blank (PatternObject , ABC ):
2929 arg_counts = [0 , 1 ]
30-
30+ target_head : OptionalType [ Symbol ]
3131 _instance = None
3232
3333 def __new__ (cls , * args , ** kwargs ):
@@ -49,12 +49,14 @@ def init(
4949 ) -> None :
5050 super ().init (expr , evaluation = evaluation )
5151 if expr .elements :
52- self .head = expr .elements [0 ]
52+ target_head = expr .elements [0 ]
53+ assert isinstance (target_head , Symbol )
54+ self .target_head = target_head
5355 else :
54- # FIXME: elswhere , some code wants to
56+ # FIXME: elsewhere , some code wants to
5557 # get the attributes of head.
5658 # So is this really the best thing to do here?
57- self .head = None
59+ self .target_head = None
5860
5961
6062class Blank (_Blank ):
@@ -100,15 +102,17 @@ class Blank(_Blank):
100102 summary_text = "match to any single expression"
101103
102104 def match (self , expression : BaseElement , pattern_context : dict ):
105+ if expression .has_form ("Sequence" , 0 ):
106+ return
107+
108+ target_head = self .target_head
109+ if target_head is not None and expression .get_head () is not target_head :
110+ return
111+
112+ # Match!
103113 vars_dict = pattern_context ["vars_dict" ]
104114 yield_func = pattern_context ["yield_func" ]
105-
106- if not expression .has_form ("Sequence" , 0 ):
107- if self .head is not None :
108- if expression .get_head ().sameQ (self .head ):
109- yield_func (vars_dict , None )
110- else :
111- yield_func (vars_dict , None )
115+ yield_func (vars_dict , None )
112116
113117 @property
114118 def element_order (self ):
@@ -157,19 +161,26 @@ class BlankNullSequence(_Blank):
157161
158162 def match (self , expression : Expression , pattern_context : dict ):
159163 """Match with a BlankNullSequence"""
160- vars_dict = pattern_context ["vars_dict" ]
161- yield_func = pattern_context ["yield_func" ]
162- elements = expression .get_sequence ()
163- if self .head :
164- ok = True
164+
165+ target_head = self .target_head
166+ if target_head :
167+ elements = expression .get_sequence ()
168+ is_uniform = False
169+ if isinstance (expression , Expression ):
170+ element_properties = expression .elements_properties
171+ if element_properties is not None :
172+ is_uniform = element_properties .is_uniform
165173 for element in elements :
166- if element .get_head () != self .head :
167- ok = False
174+ if target_head is not element .get_head ():
175+ return
176+ # If the expression is uniform, no further checks are necessary.
177+ if is_uniform :
168178 break
169- if ok :
170- yield_func (vars_dict , None )
171- else :
172- yield_func (vars_dict , None )
179+
180+ # Match!
181+ vars_dict = pattern_context ["vars_dict" ]
182+ yield_func = pattern_context ["yield_func" ]
183+ yield_func (vars_dict , None )
173184
174185 @property
175186 def element_order (self ) -> tuple :
@@ -240,21 +251,29 @@ class BlankSequence(_Blank):
240251 summary_text = "match to a non-empty sequence of elements"
241252
242253 def match (self , expression : Expression , pattern_context : dict ):
243- vars_dict = pattern_context ["vars_dict" ]
244- yield_func = pattern_context ["yield_func" ]
245254 elements = expression .get_sequence ()
255+
246256 if not elements :
247257 return
248- if self .head :
249- ok = True
258+
259+ target_head = self .target_head
260+ if target_head :
261+ is_uniform = False
262+ if isinstance (expression , Expression ):
263+ element_properties = expression .elements_properties
264+ if element_properties is not None :
265+ is_uniform = element_properties .is_uniform
250266 for element in elements :
251- if element .get_head () != self .head :
252- ok = False
267+ if target_head is not element .get_head ():
268+ return
269+ # If the expression is uniform, no further checks are necessary.
270+ if is_uniform :
253271 break
254- if ok :
255- yield_func (vars_dict , None )
256- else :
257- yield_func (vars_dict , None )
272+
273+ # Match!
274+ vars_dict = pattern_context ["vars_dict" ]
275+ yield_func = pattern_context ["yield_func" ]
276+ yield_func (vars_dict , None )
258277
259278 def get_match_count (self , vars_dict : OptionalType [dict ] = None ) -> tuple :
260279 return (1 , None )
0 commit comments