@@ -814,7 +814,7 @@ def __getitem__(self, key):
814814 key += self .__layout .length
815815 shape = self .__layout .elem_shape
816816 value = self .__target [key * elem_width :(key + 1 ) * elem_width ]
817- elif isinstance (key , (int , Value , ValueCastable )):
817+ elif isinstance (key , (Value , ValueCastable )):
818818 shape = self .__layout .elem_shape
819819 value = self .__target .word_select (key , elem_width )
820820 else :
@@ -1044,16 +1044,38 @@ def __getitem__(self, key):
10441044 :meth:`.ShapeCastable.from_bits`. Usually this will be a :exc:`ValueError`.
10451045 """
10461046 if isinstance (self .__layout , ArrayLayout ):
1047- if isinstance (key , (Value , ValueCastable )):
1047+ elem_width = Shape .cast (self .__layout .elem_shape ).width
1048+ if isinstance (key , slice ):
1049+ start , stop , stride = key .indices (self .__layout .length )
1050+ shape = ArrayLayout (self .__layout .elem_shape , len (range (start , stop , stride )))
1051+ if stride == 1 :
1052+ value = (self .__target >> start * elem_width ) & ((1 << elem_width * (stop - start )) - 1 )
1053+ else :
1054+ value = 0
1055+ pos = 0
1056+ for index in range (start , stop , stride ):
1057+ elem_value = (self .__target >> index * elem_width ) & ((1 << elem_width ) - 1 )
1058+ value |= elem_value << pos
1059+ pos += elem_width
1060+ elif isinstance (key , int ):
1061+ if key not in range (- self .__layout .length , self .__layout .length ):
1062+ raise IndexError (f"Index { key } is out of range for array layout of length "
1063+ f"{ self .__layout .length } " )
1064+ if key < 0 :
1065+ key += self .__layout .length
1066+ shape = self .__layout .elem_shape
1067+ value = (self .__target >> key * elem_width ) & ((1 << elem_width ) - 1 )
1068+ elif isinstance (key , (Value , ValueCastable )):
10481069 return View (self .__layout , self .as_value ())[key ]
1049- if not isinstance ( key , int ) :
1070+ else :
10501071 raise TypeError (
10511072 f"Constant with array layout may only be indexed with an integer or a value, "
10521073 f"not { key !r} " )
1053- shape = self .__layout .elem_shape
1054- elem_width = Shape .cast (self .__layout .elem_shape ).width
1055- value = (self .__target >> key * elem_width ) & ((1 << elem_width ) - 1 )
10561074 else :
1075+ if isinstance (key , slice ):
1076+ raise TypeError (
1077+ "Non-array constant cannot be indexed with a slice; did you mean to call "
1078+ "`.as_value()` first?" )
10571079 if isinstance (key , (Value , ValueCastable )):
10581080 raise TypeError (
10591081 f"Only constants with array layout, not { self .__layout !r} , may be indexed with "
@@ -1096,6 +1118,12 @@ def __getattr__(self, name):
10961118 f"may only be accessed by indexing" )
10971119 return item
10981120
1121+ def __len__ (self ):
1122+ if not isinstance (self .__layout , ArrayLayout ):
1123+ raise TypeError (
1124+ f"`len()` can only be used on constants of array layout, not { self .__layout !r} " )
1125+ return self .__layout .length
1126+
10991127 def __eq__ (self , other ):
11001128 if isinstance (other , View ) and self .__layout == other ._View__layout :
11011129 return self .as_value () == other ._View__target
0 commit comments