Yes, I'm thinking along the same lines. Right now this is my best shot:
A new lfun `[..] to handle all range operations. In the long run `[] no longer will be used for that, so that it can concentrate on single element indexing (which really is a fairly different operation).
`[..] would get this type:
mixed `[..] (int lower_bound_type, int lower_bound, int upper_bound_type, int upper_bound);
The bound type arguments say what type of bound was given, either a normal from-the-start bound, a from-the-end bound, or unspecified (i.e. as the first bound in a[..x]). This gives complete control to the object so that it's possible to implement data types with indeterminate lengths and/or with "real" indexing below zero.
lower_bound_type and upper_bound_type could be combined to a single bit field, but it's probably overall more expensive to do the necessary bit operations on that instead of passing them separately.
For compatibility, there'll be a fallback to `[] which then is called like this for all types of range operations:
o[a..b] => o->`[] (a, b) o[a..<b] => o->`[] (a, o->_sizeof()-1-b) o[a..] => o->`[] (a, Pike.NATIVE_MAX) o[<a..b] => o->`[] (o->_sizeof()-1-a, b) o[<a..<b] => o->`[] (o->_sizeof()-1-a, o->_sizeof()-1-b) o[<a..] => o->`[] (o->_sizeof()-1-a, Pike.NATIVE_MAX) o[..b] => o->`[] (0, b) o[..<b] => o->`[] (0, o->_sizeof()-1-b) o[..] => o->`[] (0, Pike.NATIVE_MAX)
The unfortunate thing with this fallback is that one can't define a class with element indexing but without range indexing, which is a very common case. Maybe there could be a runtime type check that `[] takes more than one argument before trying this fallback.