On Sat, Jun 13, 2015 at 9:21 AM, Nick Coghlan email@example.com wrote:
On 13 June 2015 at 20:25, Ben Leslie firstname.lastname@example.org wrote:
Is there any reason an f_stack attribute is not exposed for frames? Many
other PyFrameObject values are exposed. I'm guessing that there probably aren't too many places where you can get hold of a frame that doesn't
empty stack in normal operation, so it probably isn't necessary.
There's also the fact that anything we do in CPython that assumes a value stack based interpreter implementation might not work on other Python implementations, so we generally try to keep that level of detail hidden.
Anyway, I'm not suggesting that adding f_stack is better than explicitly adding pointers, but it does seem a more general thing that can be
and enable this use case without requiring extra book-keeping data
Emulating CPython frames on other implementations is already hard enough, without exposing the value stack directly.
I'm not sure how strong this argument is. We also expose bytecode, which is about as unportable as anything. (Though arguably we can't keep bytecode a secret, because it's written to .pyc files.) I find Ben's implementation pretty straightforward, and because it makes a copy, I don't think there's anything one could do with the exposed stack that could violate any of the interpreter's invariants (I might change it to return a tuple to emphasize this point to the caller though).
But I agree it isn't a solution to the question about the suspension "stack".
Compared to "emulate CPython's value stack", "keep track of delegation to subiterators and subcoroutines" is a far more reasonable request to make of developers of other implementations.
From a learnability perspective, there's also nothing about an "f_stack" attribute that says "you can use this to find out where a generator or coroutine has delegated control", while attributes like "gi_delegate" or "cr_delegate" would be more self-explanatory.
Stack frame objects are kind of expensive and I would hate to add an extra pointer to every frame just to support this functionality. Perhaps we could have a flag though that says whether the top of the stack is in fact the generator object on which we're waiting in a yield-from? This flag could perhaps sit next to f_executing (also note that this new flag is mutually exclusive with f_executing). We could then easily provide a new method or property on the frame object that returns the desired generator if the flag is set or None if the flag is not set -- other Python implementations could choose to implement this differently.