-
Notifications
You must be signed in to change notification settings - Fork 0
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
Support global and nonlocal statements for finding variables in scopes #250
Comments
Original comment by BitBucket: ceridwenv, GitHub: ceridwenv: The best solution to this, which isn't going to be easy in any event, is probably double-dispatch using a class and single-dispatch methods: have one subclass for each root node with different behavior with respect to |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: PCManticore): Couldn't this be implemented in a simpler way by going bottom-up, from the nonlocal / global nodes traversing into outer scopes and dealing with labels at each step? |
Original comment by Claudiu Popa (BitBucket: PCManticore, GitHub: PCManticore): I think I'm lost in these processing details. Could you write up a small proof of concept that expresses the ideas you're having for this? I'm not sure for instance which information you need to pass within scopes and why can't it be solved with a recursive algorithm. Talking on pseudo-code will be much easier. |
Original comment by BitBucket: ceridwenv, GitHub: ceridwenv: To be clear, I don't have any plans to implement this, I'm merely writing notes so that whoever's unfortunate to have to, possibly me, will have some starting points. My thinking before was partially incorrect, so I understand your confusion. I'll try to clarify. Here's a running example. print(locals())
def f():
global b
a = None
b = 'bar'
print(locals())
def g():
nonlocal a
a = 42
print(locals())
return a
g()
print(locals())
return a
print(f())
print(locals()) Now assume that I've called get_locals() at the module level, to get the globals/locals for the module, and that I'm inside an inner scope, in this case @_get_globals.register(base.NodeNG)
def globals_generic(node, locals_, global_names):
for n in node.get_children():
_get_globals(node, locals_, global_names)
@_get_globals.register(node_classes.Global)
def globals_global(node, locals_, global_names):
globals_names.extend(node.names)
@_get_globals.register(node_classes.FunctionDef)
@_get_globals.register(node_classes.ClassDef)
def globals_new_scope(node, locals_, global_names):
global_names = []
for n in node.get_children():
_get_globals(node, locals_, global_names) Passing down a mutable object does work here, I think, or rather, it would if CPython enforced the first restriction discussed in my link to the CPython documentation. However, it doesn't, so if I do this: def f():
a = None
b = 'bar'
print(locals())
def g():
...
g()
print(locals())
global b
return a The above code won't figure out that the assignment to What makes it worse, though, is that nonlocal and global statements in functions aren't executed until the function is executed. If I remove the call to I have edited some parts of my previous notes to make it clear I was wrong. |
Originally reported by: BitBucket: ceridwenv, GitHub: ceridwenv
As of modular-locals, I'm going to be removing support for global and nonlocal statements in variable scope calculations for ASTs. The current code is buggy (it doesn't support globals in class statements, it neither enforces all the restrictions in https://docs.python.org/3.5/reference/simple_stmts.html#the-global-statement nor is as liberal as the current CPython parser) and doesn't support
nonlocal
anyways, and implementing support would involve significant amounts of work and complicated code in the otherwise-simple get_locals function.The text was updated successfully, but these errors were encountered: