
Yes, mostly because there are so many variants based on the kind of loading and storing: for each load-type operator you need 11 GETSET operators, and there are many different load operators: local, global, unspecified (== local by dict instead), by attribute, by index, or by slice...
Except if you add a new type of bytecode, the 2-argument type. Which is what my implementation currently does. It necessitates just 9 new bytecodes that way: GETSET_SUBSCR, SLICE+0 through SLICE+3, NAME, FAST, GLOBAL and ATTR. The last four need 2 arguments, one for the name-index (or local vrbl number) and one for the actual operation.
But the two-arg opcode format slows down the opcode decoding -- and that's the most time-critical part of all of ceval.c!
I am still neutral on the choice between a single AUGOP with an argument that takes an argument specifying the opcode, and 11 new operators: AUGASS_ADD, ... (Actually, the latter seem the most logical given that we also have BINARY_ADD, ...)
Agreed. However, there isn't enough place in the current bytecode ranges for 9 consecutive non-argument opcodes. I'm also not sure how scarce a commodity opcodes are. Then again, it can also be 'undone' later.
There's no need for them to be consecutive! (The BINARY_* family isn't even consecutive!) I say, just some open ranges, like 54-59 and 73-79.
Yes. How about a ROT_ANY <x> argument opcode while we're at it ? <x> would specify the number to rotate... you could even encode *how* to rotate in that argument. (using the upper byte, imposing a sensible limit of 255 for the number of rotations ;-)
No, let's not overgeneralize.
Another alternative that tries to preserve compatibility is to call __getslice__(self, start, end) when the step is None, but __getslice__(self, start, end, step) when it isn't. Old code will raise a reasonable exception when a step is specified, while step-aware code can specify the step as a default argument value of 1 or None.
Yes, that's very reasonable. I would suggest making the error 'special', in this case, though. So that you don't get a TypeError about incorrect number of arguments, but rather a 'object does not support extended slices' or some such TypeError.
Yes.
Actually, it might be worth doing it like this:
Try to call __getslice__ with unconverted start, stop and step If it fails with a TypeError, and step is not None, raise the above error Else, convert start and stop to ints like the current normal slice behaviour, and try __getslice__ the old way.
No, trying to call something and retrying if it fails is a bad idea: the code might fail for a very different reason, and retrying it might mask the bug, or execute a side effect twice... There's no reason why we can't check whether the step is None; it's already impossible to find out whether a particular slice was "lo:hi:None" or "lo:hi:" (once extended slice mode is used). --Guido van Rossum (home page: http://www.pythonlabs.com/~guido/)