@@ -38,10 +38,14 @@ func checkBounds(ast *Node, input any, idx int) Error {
3838 }
3939 }
4040 if v , ok := input .(string ); ok {
41- length := stringLength (v )
42- if idx < 0 || idx >= length {
43- return NewError (ast .Offset , ast .Length , "invalid index %d for string of length %d" , int (idx ), length )
44- }
41+ return checkStringBounds (ast , stringLength (v ), idx )
42+ }
43+ return nil
44+ }
45+
46+ func checkStringBounds (ast * Node , length , idx int ) Error {
47+ if idx < 0 || idx >= length {
48+ return NewError (ast .Offset , ast .Length , "invalid index %d for string of length %d" , idx , length )
4549 }
4650 return nil
4751}
@@ -166,6 +170,60 @@ func (i *interpreter) run(ast *Node, value any) (any, Error) {
166170 if ! isSlice (resultLeft ) && ! isString (resultLeft ) {
167171 return nil , NewError (ast .Offset , ast .Length , "can only index strings or arrays but got %v" , resultLeft )
168172 }
173+ if ast .Right != nil && ast .Right .Type == NodeSlice {
174+ startValue , err := i .run (ast .Right .Left , value )
175+ if err != nil {
176+ return nil , err
177+ }
178+ endValue , err := i .run (ast .Right .Right , value )
179+ if err != nil {
180+ return nil , err
181+ }
182+ start , err := toNumber (ast .Right .Left , startValue )
183+ if err != nil {
184+ return nil , err
185+ }
186+ end , err := toNumber (ast .Right .Right , endValue )
187+ if err != nil {
188+ return nil , err
189+ }
190+ if left , ok := resultLeft .([]any ); ok {
191+ if start < 0 {
192+ start += float64 (len (left ))
193+ }
194+ if end < 0 {
195+ end += float64 (len (left ))
196+ }
197+ if err := checkBounds (ast , left , int (start )); err != nil {
198+ return nil , err
199+ }
200+ if err := checkBounds (ast , left , int (end )); err != nil {
201+ return nil , err
202+ }
203+ if int (start ) > int (end ) {
204+ return nil , NewError (ast .Offset , ast .Length , "slice start cannot be greater than end" )
205+ }
206+ return left [int (start ) : int (end )+ 1 ], nil
207+ }
208+ left := toString (resultLeft )
209+ leftLen := stringLength (left )
210+ if start < 0 {
211+ start += float64 (leftLen )
212+ }
213+ if end < 0 {
214+ end += float64 (leftLen )
215+ }
216+ if err := checkStringBounds (ast , leftLen , int (start )); err != nil {
217+ return nil , err
218+ }
219+ if int (start ) > int (end ) {
220+ return nil , NewError (ast .Offset , ast .Length , "string slice start cannot be greater than end" )
221+ }
222+ if err := checkStringBounds (ast , leftLen , int (end )); err != nil {
223+ return nil , err
224+ }
225+ return stringSlice (left , int (start ), int (end )), nil
226+ }
169227 resultRight , err := i .run (ast .Right , value )
170228 if err != nil {
171229 return nil , err
@@ -205,13 +263,13 @@ func (i *interpreter) run(ast *Node, value any) (any, Error) {
205263 if end < 0 {
206264 end += float64 (leftLen )
207265 }
208- if err := checkBounds (ast , left , int (start )); err != nil {
266+ if err := checkStringBounds (ast , leftLen , int (start )); err != nil {
209267 return nil , err
210268 }
211269 if int (start ) > int (end ) {
212270 return nil , NewError (ast .Offset , ast .Length , "string slice start cannot be greater than end" )
213271 }
214- if err := checkBounds (ast , left , int (end )); err != nil {
272+ if err := checkStringBounds (ast , leftLen , int (end )); err != nil {
215273 return nil , err
216274 }
217275 return stringSlice (left , int (start ), int (end )), nil
@@ -231,10 +289,11 @@ func (i *interpreter) run(ast *Node, value any) (any, Error) {
231289 return left [int (idx )], nil
232290 }
233291 left := toString (resultLeft )
292+ leftLen := stringLength (left )
234293 if idx < 0 {
235- idx += float64 (stringLength ( left ) )
294+ idx += float64 (leftLen )
236295 }
237- if err := checkBounds (ast , left , int (idx )); err != nil {
296+ if err := checkStringBounds (ast , leftLen , int (idx )); err != nil {
238297 return nil , err
239298 }
240299 return stringIndex (left , int (idx )), nil
0 commit comments