@@ -281,6 +281,37 @@ def __init__(self, low, high):
281281 self .low = pop_expr ()
282282 to_expr (high )
283283 self .high = pop_expr ()
284+
285+ def _safe_to_expr_model (value ):
286+ """
287+ Safely convert a value to an expression model.
288+
289+ This function creates an expr object via to_expr() and extracts the
290+ expression model (.em) directly. It also attempts to pop from the global
291+ expression stack to maintain balance, but handles IndexError gracefully
292+ in case the stack is empty or corrupted (which can happen during constraint
293+ solving failures).
294+
295+ Note: to_expr() either:
296+ - Creates a new expr object (which pushes to stack in __init__), OR
297+ - Returns an existing expr object that's already on the stack
298+ In both cases, we need to pop to maintain stack balance.
299+
300+ Args:
301+ value: The value to convert to an expression model
302+
303+ Returns:
304+ The expression model object
305+ """
306+ expr_obj = to_expr (value )
307+ model = expr_obj .em
308+ # Try to maintain stack balance, but don't fail if stack is corrupted
309+ try :
310+ pop_expr ()
311+ except IndexError :
312+ # Stack was empty or corrupted, but we have the expression model
313+ pass
314+ return model
284315
285316class rangelist (object ):
286317
@@ -295,21 +326,18 @@ def __init__(self, *args):
295326 # This needs to be a two-element array
296327 if len (a ) != 2 :
297328 raise Exception ("Range specified with " + str (len (a )) + " elements is invalid. Two elements required" )
298- to_expr (a [0 ])
299- e0 = pop_expr ()
300- to_expr (a [1 ])
301- e1 = pop_expr ()
329+ # Use helper to safely get expression models
330+ e0 = _safe_to_expr_model (a [0 ])
331+ e1 = _safe_to_expr_model (a [1 ])
302332 self .range_l .add_range (ExprRangeModel (e0 , e1 ))
303333 elif isinstance (a , rng ):
304334 self .range_l .add_range (ExprRangeModel (a .low , a .high ))
305335 elif isinstance (a , list ):
306336 for ai in a :
307- to_expr (ai )
308- eai = pop_expr ()
337+ eai = _safe_to_expr_model (ai )
309338 self .range_l .add_range (eai )
310339 else :
311- to_expr (a )
312- e = pop_expr ()
340+ e = _safe_to_expr_model (a )
313341 self .range_l .add_range (e )
314342# self.range_l.rl.reverse()
315343
@@ -327,26 +355,23 @@ def append(self, a):
327355 # This needs to be a two-element array
328356 if len (a ) != 2 :
329357 raise Exception ("Range specified with " + str (len (a )) + " elements is invalid. Two elements required" )
330- to_expr (a [0 ])
331- e0 = pop_expr ()
332- to_expr (a [1 ])
333- e1 = pop_expr ()
358+ # Use helper to safely get expression models
359+ e0 = _safe_to_expr_model (a [0 ])
360+ e1 = _safe_to_expr_model (a [1 ])
334361 self .range_l .add_range (ExprRangeModel (e0 , e1 ))
335362 elif isinstance (a , rng ):
336363 self .range_l .add_range (ExprRangeModel (a .low , a .high ))
337364 elif isinstance (a , list ):
338365 for ai in a :
339- to_expr (ai )
340- eai = pop_expr ()
366+ eai = _safe_to_expr_model (ai )
341367 self .range_l .add_range (eai )
342368 else :
343- to_expr (a )
344- e = pop_expr ()
369+ e = _safe_to_expr_model (a )
345370 self .range_l .add_range (e )
346371
347372 def __contains__ (self , lhs ):
348- to_expr (lhs )
349- return expr (ExprInModel (pop_expr () , self .range_l ))
373+ lhs_model = _safe_to_expr_model (lhs )
374+ return expr (ExprInModel (lhs_model , self .range_l ))
350375
351376 def __invert__ (self ):
352377 print ("rangelist.__invert__" )
0 commit comments