@@ -173,6 +173,8 @@ def then_else(self, then_val: IteType, else_val: IteType) -> IteType:
173173class NumLikeExpr (ConstraintExpr [WrappedType , NumLikeCastable ], Generic [WrappedType , NumLikeCastable ]):
174174 """Trait for numeric-like expressions, providing common arithmetic operations"""
175175
176+ _CASTABLE_TYPES : Tuple [Type [NumLikeCastable ], ...] # NumLikeCastable for use in ininstance(), excluding self-cls
177+
176178 @classmethod
177179 @abstractmethod
178180 def _to_expr_type (cls : Type [NumLikeSelfType ],
@@ -209,28 +211,44 @@ def __mul_inv__(self: NumLikeSelfType) -> NumLikeSelfType:
209211 return self ._create_unary_op (self , NumericOp .invert )
210212
211213 def __add__ (self : NumLikeSelfType , rhs : NumLikeCastable ) -> NumLikeSelfType :
212- return self ._create_binary_op (self , self ._to_expr_type (rhs ), NumericOp .add )
214+ if isinstance (rhs , self ._CASTABLE_TYPES ) or isinstance (rhs , self .__class__ ):
215+ return self ._create_binary_op (self , self ._to_expr_type (rhs ), NumericOp .add )
216+ return NotImplemented
213217
214218 def __radd__ (self : NumLikeSelfType , lhs : NumLikeCastable ) -> NumLikeSelfType :
215- return self ._create_binary_op (self ._to_expr_type (lhs ), self , NumericOp .add )
219+ if isinstance (lhs , self ._CASTABLE_TYPES ) or isinstance (lhs , self .__class__ ):
220+ return self ._create_binary_op (self ._to_expr_type (lhs ), self , NumericOp .add )
221+ return NotImplemented
216222
217223 def __sub__ (self : NumLikeSelfType , rhs : NumLikeCastable ) -> NumLikeSelfType :
218- return self .__add__ (self ._to_expr_type (rhs ).__neg__ ())
224+ if isinstance (rhs , self ._CASTABLE_TYPES ) or isinstance (rhs , self .__class__ ):
225+ return self .__add__ (self ._to_expr_type (rhs ).__neg__ ())
226+ return NotImplemented
219227
220228 def __rsub__ (self : NumLikeSelfType , lhs : NumLikeCastable ) -> NumLikeSelfType :
221- return self .__neg__ ().__radd__ (self ._to_expr_type (lhs ))
229+ if isinstance (lhs , self ._CASTABLE_TYPES ) or isinstance (lhs , self .__class__ ):
230+ return self .__neg__ ().__radd__ (self ._to_expr_type (lhs ))
231+ return NotImplemented
222232
223233 def __mul__ (self : NumLikeSelfType , rhs : NumLikeCastable ) -> NumLikeSelfType :
224- return self ._create_binary_op (self , self ._to_expr_type (rhs ), NumericOp .mul )
234+ if isinstance (rhs , self ._CASTABLE_TYPES ) or isinstance (rhs , self .__class__ ):
235+ return self ._create_binary_op (self , self ._to_expr_type (rhs ), NumericOp .mul )
236+ return NotImplemented
225237
226238 def __rmul__ (self : NumLikeSelfType , lhs : NumLikeCastable ) -> NumLikeSelfType :
227- return self ._create_binary_op (self ._to_expr_type (lhs ), self , NumericOp .mul )
239+ if isinstance (lhs , self ._CASTABLE_TYPES ) or isinstance (lhs , self .__class__ ):
240+ return self ._create_binary_op (self ._to_expr_type (lhs ), self , NumericOp .mul )
241+ return NotImplemented
228242
229243 def __truediv__ (self : NumLikeSelfType , rhs : NumLikeCastable ) -> NumLikeSelfType :
230- return self .__mul__ (self ._to_expr_type (rhs ).__mul_inv__ ())
244+ if isinstance (rhs , self ._CASTABLE_TYPES ) or isinstance (rhs , self .__class__ ):
245+ return self .__mul__ (self ._to_expr_type (rhs ).__mul_inv__ ())
246+ return NotImplemented
231247
232248 def __rtruediv__ (self : NumLikeSelfType , lhs : NumLikeCastable ) -> NumLikeSelfType :
233- return self .__mul_inv__ ().__mul__ (self ._to_expr_type (lhs ))
249+ if isinstance (lhs , self ._CASTABLE_TYPES ) or isinstance (lhs , self .__class__ ):
250+ return self .__mul_inv__ ().__mul__ (self ._to_expr_type (lhs ))
251+ return NotImplemented
234252
235253 @classmethod
236254 def _create_bool_op (cls ,
@@ -245,23 +263,35 @@ def _create_bool_op(cls,
245263 return BoolExpr ()._bind (BinaryOpBinding (lhs , rhs , op ))
246264
247265 def __ne__ (self : NumLikeSelfType , other : NumLikeCastable ) -> BoolExpr : #type: ignore
248- return self ._create_bool_op (self , self ._to_expr_type (other ), EqOp .ne )
266+ if isinstance (other , self ._CASTABLE_TYPES ) or isinstance (other , self .__class__ ):
267+ return self ._create_bool_op (self , self ._to_expr_type (other ), EqOp .ne )
268+ return NotImplemented
249269
250270 def __gt__ (self : NumLikeSelfType , other : NumLikeCastable ) -> BoolExpr : #type: ignore
251- return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .gt )
271+ if isinstance (other , self ._CASTABLE_TYPES ) or isinstance (other , self .__class__ ):
272+ return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .gt )
273+ return NotImplemented
252274
253275 def __ge__ (self : NumLikeSelfType , other : NumLikeCastable ) -> BoolExpr : #type: ignore
254- return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .ge )
276+ if isinstance (other , self ._CASTABLE_TYPES ) or isinstance (other , self .__class__ ):
277+ return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .ge )
278+ return NotImplemented
255279
256280 def __lt__ (self : NumLikeSelfType , other : NumLikeCastable ) -> BoolExpr : #type: ignore
257- return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .lt )
281+ if isinstance (other , self ._CASTABLE_TYPES ) or isinstance (other , self .__class__ ):
282+ return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .lt )
283+ return NotImplemented
258284
259285 def __le__ (self : NumLikeSelfType , other : NumLikeCastable ) -> BoolExpr : #type: ignore
260- return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .le )
286+ if isinstance (other , self ._CASTABLE_TYPES ) or isinstance (other , self .__class__ ):
287+ return self ._create_bool_op (self , self ._to_expr_type (other ), OrdOp .le )
288+ return NotImplemented
261289
262290
263291IntLike = Union ['IntExpr' , int ]
264292class IntExpr (NumLikeExpr [int , IntLike ]):
293+ _CASTABLE_TYPES = (int , )
294+
265295 @classmethod
266296 def _to_expr_type (cls , input : IntLike ) -> IntExpr :
267297 if isinstance (input , IntExpr ):
@@ -287,6 +317,8 @@ def _from_lit(cls, pb: edgir.ValueLit) -> int:
287317FloatLit = Union [float , int ]
288318FloatLike = Union ['FloatExpr' , float , int ]
289319class FloatExpr (NumLikeExpr [float , Union [FloatLike , IntExpr ]]):
320+ _CASTABLE_TYPES = (float , int )
321+
290322 @classmethod
291323 def _to_expr_type (cls , input : Union [FloatLike , IntExpr ]) -> FloatExpr :
292324 if isinstance (input , FloatExpr ):
@@ -320,6 +352,9 @@ def max(self, other: FloatLike) -> FloatExpr:
320352
321353RangeLike = Union ['RangeExpr' , Range , Tuple [FloatLike , FloatLike ]]
322354class RangeExpr (NumLikeExpr [Range , Union [RangeLike , FloatLike , IntExpr ]]):
355+ # mypy doesn't like the unbounded tuple
356+ _CASTABLE_TYPES = (float , int , FloatExpr , IntExpr , Range , tuple ) # type: ignore
357+
323358 # Some range literals for defaults
324359 POSITIVE : Range = Range .from_lower (0.0 )
325360 NEGATIVE : Range = Range .from_upper (0.0 )
@@ -424,26 +459,6 @@ def _create_range_float_binary_op(cls,
424459 assert lhs ._is_bound () and rhs ._is_bound ()
425460 return lhs ._new_bind (BinaryOpBinding (lhs , rhs , op ))
426461
427- # special option to allow range * float
428- def __mul__ (self , rhs : Union [RangeLike , FloatLike , IntLike ]) -> RangeExpr :
429- if isinstance (rhs , (int , float )): # TODO clean up w/ literal to expr pass, then type based on that
430- rhs_cast : Union [FloatExpr , IntExpr , RangeExpr ] = FloatExpr ._to_expr_type (rhs )
431- elif isinstance (rhs , (FloatExpr , IntExpr )):
432- rhs_cast = rhs
433- else :
434- rhs_cast = self ._to_expr_type (rhs ) # type: ignore
435- return self ._create_range_float_binary_op (self , rhs_cast , NumericOp .mul )
436-
437- # special option to allow range / float
438- def __truediv__ (self , rhs : Union [RangeLike , FloatLike , IntLike ]) -> RangeExpr :
439- if isinstance (rhs , (int , float )): # TODO clean up w/ literal to expr pass, then type based on that
440- rhs_cast : Union [FloatExpr , IntExpr , RangeExpr ] = FloatExpr ._to_expr_type (rhs )
441- elif isinstance (rhs , (FloatExpr , IntExpr )):
442- rhs_cast = rhs
443- else :
444- rhs_cast = self ._to_expr_type (rhs ) # type: ignore
445- return self * rhs_cast .__mul_inv__ ()
446-
447462 def shrink_multiply (self , contributing : RangeLike ) -> RangeExpr :
448463 """RangeExpr version of Range.shrink_multiply.
449464 See docs for Range.shrink_multiply."""
0 commit comments