@@ -814,7 +814,7 @@ def __getitem__(self, key):
814
814
key += self .__layout .length
815
815
shape = self .__layout .elem_shape
816
816
value = self .__target [key * elem_width :(key + 1 ) * elem_width ]
817
- elif isinstance (key , (int , Value , ValueCastable )):
817
+ elif isinstance (key , (Value , ValueCastable )):
818
818
shape = self .__layout .elem_shape
819
819
value = self .__target .word_select (key , elem_width )
820
820
else :
@@ -1044,16 +1044,38 @@ def __getitem__(self, key):
1044
1044
:meth:`.ShapeCastable.from_bits`. Usually this will be a :exc:`ValueError`.
1045
1045
"""
1046
1046
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 )):
1048
1069
return View (self .__layout , self .as_value ())[key ]
1049
- if not isinstance ( key , int ) :
1070
+ else :
1050
1071
raise TypeError (
1051
1072
f"Constant with array layout may only be indexed with an integer or a value, "
1052
1073
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 )
1056
1074
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?" )
1057
1079
if isinstance (key , (Value , ValueCastable )):
1058
1080
raise TypeError (
1059
1081
f"Only constants with array layout, not { self .__layout !r} , may be indexed with "
@@ -1096,6 +1118,12 @@ def __getattr__(self, name):
1096
1118
f"may only be accessed by indexing" )
1097
1119
return item
1098
1120
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
+
1099
1127
def __eq__ (self , other ):
1100
1128
if isinstance (other , View ) and self .__layout == other ._View__layout :
1101
1129
return self .as_value () == other ._View__target
0 commit comments