1515from typed_python .compiler .type_wrappers .wrapper import Wrapper
1616from typed_python .compiler .merge_type_wrappers import mergeTypes
1717from typed_python import (
18- _types , Int32 , Tuple , NamedTuple , Function , Dict , Set , ConstDict , ListOf , TupleOf
18+ _types , Int32 , Tuple , NamedTuple , Function , Dict , Set , ConstDict , ListOf ,
19+ TupleOf , PointerTo , pointerTo , TypeFunction , OneOf , Class , Member , Final
1920)
2021import typed_python ._types
2122from typed_python .compiler .conversion_level import ConversionLevel
@@ -195,6 +196,9 @@ def __init__(self, t):
195196 self ._is_pod = all (typeWrapper (possibility ).is_pod for possibility in self .subTypeWrappers )
196197 self .is_default_constructible = _types .is_default_constructible (t )
197198
199+ def isIterable (self ):
200+ return True
201+
198202 @property
199203 def unionType (self ):
200204 if self ._unionType is None and self .typeRepresentation .ElementTypes :
@@ -220,6 +224,23 @@ def is_pod(self):
220224 def getNativeLayoutType (self ):
221225 return self .layoutType
222226
227+ def convert_attribute (self , context , instance , attribute ):
228+ if attribute in ["__iter__" ]:
229+ return instance .changeType (BoundMethodWrapper .Make (self , attribute ))
230+
231+ return super ().convert_attribute (context , instance , attribute )
232+
233+ def convert_method_call (self , context , instance , methodname , args , kwargs ):
234+ if methodname == '__iter__' and not args :
235+ return typeWrapper (TupleIterator (self .typeRepresentation )).convert_type_call (
236+ context ,
237+ None ,
238+ [],
239+ dict (pos = context .constant (- 1 ), tup = instance )
240+ )
241+
242+ return super ().convert_method_call (context , instance , methodname , args , kwargs )
243+
223244 def convert_initialize_from_args (self , context , target , * args ):
224245 assert len (args ) <= len (self .byteOffsets )
225246
@@ -608,6 +629,9 @@ def __init__(self, t):
608629 self .namesToIndices = {n : i for i , n in enumerate (t .ElementNames )}
609630 self .namesToTypes = {n : t .ElementTypes [i ] for i , n in enumerate (t .ElementNames )}
610631
632+ def isIterable (self ):
633+ return True
634+
611635 def has_fastnext_iter (self ):
612636 if self .isSubclassOfNamedTuple :
613637 return "__iter__" in self .typeRepresentation .__dict__
@@ -869,3 +893,24 @@ def convert_bin_op_reverse(self, context, r, op, l, inplace):
869893 return self .convert_method_call (context , r , magic , (l ,), {})
870894
871895 return super ().convert_bin_op_reverse (context , r , op , l , inplace )
896+
897+
898+ @TypeFunction
899+ def TupleIterator (T ):
900+ EltT = OneOf (* T .ElementTypes )
901+
902+ class TupleIterator (Class , Final , __name__ = f"TupleIterator({ T .__name__ } )" ):
903+ pos = Member (int , nonempty = True )
904+ elt = Member (EltT )
905+ tup = Member (T , nonempty = True )
906+
907+ def __fastnext__ (self ):
908+ self .pos += 1
909+
910+ if self .pos < len (self .tup ):
911+ self .elt = self .tup [self .pos ]
912+ return pointerTo (self ).elt
913+ else :
914+ return PointerTo (EltT )()
915+
916+ return TupleIterator
0 commit comments