44import functools
55import inspect
66import operator
7- from typing import Any
7+ from typing import Any , Optional
88
99import cython
1010
11+ from .utils import PseudoHashable
12+
1113Context = dict [str , Any ]
1214
1315
@@ -64,9 +66,6 @@ def __getitem__(self, name):
6466 def __call__ (self , * args , ** kwargs ):
6567 return Deferred (Call (self , * args , ** kwargs ))
6668
67- # def __contains__(self, item):
68- # return Deferred(Binop(operator.contains, self, item))
69-
7069 def __invert__ (self ) -> Deferred :
7170 return Deferred (Unop (operator .invert , self ))
7271
@@ -187,6 +186,12 @@ def build(self, ctx: Context): ...
187186 def __eq__ (self , other : Any ) -> bool :
188187 return type (self ) is type (other ) and self .equals (other )
189188
189+ def __hash__ (self ):
190+ return self ._hash ()
191+
192+ def __repr__ (self ):
193+ raise NotImplementedError (f"{ self .__class__ .__name__ } is not reprable" )
194+
190195
191196def _deferred_repr (obj ):
192197 try :
@@ -223,6 +228,9 @@ def __init__(self, func: Any):
223228 def __repr__ (self ):
224229 return _deferred_repr (self .func )
225230
231+ def _hash (self ):
232+ return hash ((self .__class__ , self .func ))
233+
226234 def equals (self , other : Func ) -> bool :
227235 return self .func == other .func
228236
@@ -247,12 +255,17 @@ class Just(Builder):
247255 def __init__ (self , value : Any ):
248256 if isinstance (value , Just ):
249257 self .value = cython .cast (Just , value ).value
258+ elif isinstance (value , (Builder , Deferred )):
259+ raise TypeError (f"`{ value } ` cannot be used as a Just value" )
250260 else :
251261 self .value = value
252262
253263 def __repr__ (self ):
254264 return _deferred_repr (self .value )
255265
266+ def _hash (self ):
267+ return hash ((self .__class__ , PseudoHashable (self .value )))
268+
256269 def equals (self , other : Just ) -> bool :
257270 return self .value == other .value
258271
@@ -279,6 +292,9 @@ def __init__(self, name: str):
279292 def __repr__ (self ):
280293 return f"${ self .name } "
281294
295+ def _hash (self ):
296+ return hash ((self .__class__ , self .name ))
297+
282298 def equals (self , other : Var ) -> bool :
283299 return self .name == other .name
284300
@@ -332,6 +348,9 @@ def __init__(self, func):
332348 def __repr__ (self ):
333349 return f"{ self .func !r} ()"
334350
351+ def _hash (self ):
352+ return hash ((self .__class__ , self .func ))
353+
335354 def equals (self , other : Call0 ) -> bool :
336355 return self .func == other .func
337356
@@ -364,6 +383,9 @@ def __init__(self, func, arg):
364383 def __repr__ (self ):
365384 return f"{ self .func !r} ({ self .arg !r} )"
366385
386+ def _hash (self ):
387+ return hash ((self .__class__ , self .func , self .arg ))
388+
367389 def equals (self , other : Call1 ) -> bool :
368390 return self .func == other .func and self .arg == other .arg
369391
@@ -401,6 +423,9 @@ def __init__(self, func, arg1, arg2):
401423 def __repr__ (self ):
402424 return f"{ self .func !r} ({ self .arg1 !r} , { self .arg2 !r} )"
403425
426+ def _hash (self ):
427+ return hash ((self .__class__ , self .func , self .arg1 , self .arg2 ))
428+
404429 def equals (self , other : Call2 ) -> bool :
405430 return (
406431 self .func == other .func
@@ -447,6 +472,9 @@ def __init__(self, func, arg1, arg2, arg3):
447472 def __repr__ (self ):
448473 return f"{ self .func !r} ({ self .arg1 !r} , { self .arg2 !r} , { self .arg3 !r} )"
449474
475+ def _hash (self ):
476+ return hash ((self .__class__ , self .func , self .arg1 , self .arg2 , self .arg3 ))
477+
450478 def equals (self , other : Call3 ) -> bool :
451479 return (
452480 self .func == other .func
@@ -482,12 +510,12 @@ class CallN(Builder):
482510 """
483511
484512 func : Builder
485- args : list [Builder ]
513+ args : tuple [Builder , ... ]
486514 kwargs : dict [str , Builder ]
487515
488516 def __init__ (self , func , * args , ** kwargs ):
489517 self .func = builder (func )
490- self .args = [ builder (arg ) for arg in args ]
518+ self .args = tuple ( builder (arg ) for arg in args )
491519 self .kwargs = {k : builder (v ) for k , v in kwargs .items ()}
492520
493521 def __repr__ (self ):
@@ -502,6 +530,9 @@ def __repr__(self):
502530 else :
503531 return f"{ self .func !r} ()"
504532
533+ def _hash (self ):
534+ return hash ((self .__class__ , self .func , self .args , PseudoHashable (self .kwargs )))
535+
505536 def equals (self , other : CallN ) -> bool :
506537 return (
507538 self .func == other .func
@@ -573,6 +604,9 @@ def __repr__(self):
573604 symbol = _operator_symbols [self .op ]
574605 return f"{ symbol } { self .arg !r} "
575606
607+ def _hash (self ):
608+ return hash ((self .__class__ , self .op , self .arg ))
609+
576610 def equals (self , other : Unop ) -> bool :
577611 return self .op == other .op and self .arg == other .arg
578612
@@ -610,6 +644,9 @@ def __repr__(self):
610644 symbol = _operator_symbols [self .op ]
611645 return f"({ self .arg1 !r} { symbol } { self .arg2 !r} )"
612646
647+ def _hash (self ):
648+ return hash ((self .__class__ , self .op , self .arg1 , self .arg2 ))
649+
613650 def equals (self , other : Binop ) -> bool :
614651 return (
615652 self .op == other .op and self .arg1 == other .arg1 and self .arg2 == other .arg2
@@ -645,6 +682,9 @@ def __init__(self, obj, key):
645682 def __repr__ (self ):
646683 return f"{ self .obj !r} [{ self .key !r} ]"
647684
685+ def _hash (self ):
686+ return hash ((self .__class__ , self .obj , self .key ))
687+
648688 def equals (self , other : Item ) -> bool :
649689 return self .obj == other .obj and self .key == other .key
650690
@@ -678,6 +718,9 @@ def __init__(self, obj: Any, attr: str):
678718 def __repr__ (self ):
679719 return f"{ self .obj !r} .{ self .attr } "
680720
721+ def _hash (self ):
722+ return hash ((self .__class__ , self .obj , self .attr ))
723+
681724 def equals (self , other : Attr ) -> bool :
682725 return self .obj == other .obj and self .attr == other .attr
683726
@@ -699,11 +742,11 @@ class Seq(Builder):
699742 """
700743
701744 type_ : Any
702- items : list [Builder ]
745+ items : tuple [Builder , ... ]
703746
704747 def __init__ (self , items ):
705748 self .type_ = type (items )
706- self .items = [ builder (item ) for item in items ]
749+ self .items = tuple ( builder (item ) for item in items )
707750
708751 def __repr__ (self ):
709752 elems = ", " .join (map (repr , self .items ))
@@ -714,6 +757,9 @@ def __repr__(self):
714757 else :
715758 return f"{ self .type_ .__name__ } ({ elems } )"
716759
760+ def _hash (self ):
761+ return hash ((self .__class__ , self .type_ , self .items ))
762+
717763 def equals (self , other : Seq ) -> bool :
718764 return self .type_ == other .type_ and self .items == other .items
719765
@@ -751,6 +797,9 @@ def __repr__(self):
751797 else :
752798 return f"{ self .type_ .__name__ } ({{{ items } }})"
753799
800+ def _hash (self ):
801+ return hash ((self .__class__ , self .type_ , PseudoHashable (self .items )))
802+
754803 def equals (self , other : Map ) -> bool :
755804 return self .type_ == other .type_ and self .items == other .items
756805
0 commit comments