-
Notifications
You must be signed in to change notification settings - Fork 266
Scope bug and generators #10
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
In PY3, we're falling back to the builtin implementation by relying on __build_class__. Add tests that show that something is going wrong with attribute lookup.
This causes the PY2 class inheiritance tests to start failing - they were only working because of this scoping bug, I think.
I've come to believe that the right implementation of the VM has one data stack per frame, not one data stack for the VM. This is consistent with halting and resuming frames using generators. The bug appeared to be around nested generators, but in fact it should arise with any generator resuming a frame if the stack has been modified in the meantime.
Wow, this is amazing! I'm humbled to learn that I had the data stack wrong, and a 5-minute look at frameobject.{h,c} confirms it! I'm confused about the PY2-only Object, etc classes. I don't remember deciding to use them differently in Py2 and Py3. Why is that? Thanks so much for this, I'm going to review it in detail. |
It took me considerably longer than that on frameobject! On the classes and objects, our code was bypassed because Py3 doesn't emit Our creation of a new Py2:
Py3:
|
code review welcome. |
Am I doing something wrong? When I run the tests on Py2.7, I get three test failures (captured stdout and logging removed):
|
On the question of our |
The three test failures are consistent with what I'm seeing. One of them - I think the class inheritance tests only ever passed because of the scoping bug, when locals in the parent frame were passed through blindly to the child, but I'm not sure about this. I haven't been able so far to write a test like |
I spent more time looking at the object system (again with @rntz, thanks rntz). We found several ways in which the existing attribute lookup code isn't true to the implementation of CPython, particularly around descriptors. (See this branch for the detailed attempt, which we didn't get working, and this commit for the tests.) The good news is that it's almost trivial to sidestep the whole object system by implementing |
I'm a little confused: I think your last comment said, "We fixed a number of bugs in XYZ, and we also completely obsoleted XYZ." (where XYZ == Python implementation of objects, classes, attribute lookup, etc). I think you are also recommending getting rid of that stuff. We still need a some of it, right? For generators and closures? Will you be working up a pull request to show what you intend? |
No. We exposed, but did not fix, a number of bugs in the implementation of user-defined classes and objects. We then obsoleted the user-defined classes and objects implementation by removing We have still implemented everything other than user-defined objects. The implementation of generators and closures is independent of these. |
The file diff on this PR shows is where I intended to end up (although I'd be happy to rebase). My comment from above would now read: This PR:
|
Let me know if I can clarify anything in these proposed changes. It looks like #12 includes correct attribute handling, so quite possibly that's the better way to go. |
I didn't even look for other in progress work on this. Sorry about that! I don't know how much time I will have to help with any of this but I'll keep an eye on this, and you should feel free to ping me if you have any questions about my request or the changes I made. |
This PR:
Fixes the implementation of generators by giving each frame its own data stack, not having one data stack for the VM (thanks to @rntz for pairing on this). I think this is consistent with the implementation of CPython. See, e.g., this blog post:
Exposes and fixes a bug around nested scoping that allowed inner function scopes to clobber outer function scopes if they had identically-named variables (this was part of the problem with generators, which set up a local variable named ".0"). The fix is to not pass through the local variables from one frame to another. I think this solution is true to the implementation of CPython and not just an ugly hack.
Exposes problems with class inheritance - I think this was only ever working because of the bad scoping bug above. I've added a test of dynamic attribute lookup that shows our old implementation wasn't right. This PR doesn't fix the class inheritance problems in Python 2, but I have spent a lot of time reading through object.c, typeobject.c, and classobject.c, so maybe I'll make some headway on that eventually.
Adds "if PY2" around the object and class implementation to make clear that we're not using them in Python 3. (We're not putting 'if PY2' and 'if PY3' around every bytecode or function that's specific to one or the other, but I think it's worth it here - I didn't realize until a few days ago that we're falling back to the builtin objects and classes in Python 3.)