Track variables marked as global in static analysis. This is needed in an upcoming CL.
PiperOrigin-RevId: 288736389 Change-Id: I2c8854d301adeb45e1ca7422b00c455f60d8f7cc
This commit is contained in:
parent
4e8a6a0324
commit
43e41f42dd
@ -63,20 +63,18 @@ class Scope(object):
|
||||
bound: Set[qual_names.QN], names that are bound to this scope. See
|
||||
https://docs.python.org/3/reference/executionmodel.html#binding-of-names
|
||||
for a precise definition.
|
||||
free: Set[qual_names.QN], names that are free variables in the context of
|
||||
this scpe. This property only matches Python's notion of free variables
|
||||
for isolated scopes. For example, the scope tracking the body of an if
|
||||
statement will count a variable that it used but not bound as free,
|
||||
even if it's actually bound elsewhere in the enclosing function.
|
||||
globals: Set[qual_names.QN], names that are explicitly marked as global in
|
||||
this scope. Note that this doesn't include free read-only vars bound to
|
||||
global symbols.
|
||||
free_vars: Set[qual_names.QN], the free variables in this scope. See
|
||||
https://docs.python.org/3/reference/executionmodel.html for a precise
|
||||
definition.
|
||||
params: WeakValueDictionary[qual_names.QN, ast.Node], function arguments
|
||||
visible in this scope, mapped to the function node that defines them.
|
||||
enclosing_scope: Scope, the innermost isolated scope that is a transitive
|
||||
parent of this scope. May be the scope itself.
|
||||
referenced: Set[qual_names.QN], the totality of the symbols used by this
|
||||
scope and its parents.
|
||||
free_vars: Set[qual_names.QN], the free variables in this scope. See
|
||||
https://docs.python.org/3/reference/executionmodel.html for a precise
|
||||
definition.
|
||||
is_final: bool, whether the scope is frozen or not.
|
||||
|
||||
Note - simple statements may never delete and modify a symbol at the same
|
||||
@ -106,6 +104,7 @@ class Scope(object):
|
||||
self.deleted = set()
|
||||
|
||||
self.bound = set()
|
||||
self.globals = set()
|
||||
|
||||
self.params = weakref.WeakValueDictionary()
|
||||
|
||||
@ -174,6 +173,7 @@ class Scope(object):
|
||||
self.parent.read.update(self.read)
|
||||
self.parent.modified.update(self.modified)
|
||||
self.parent.bound.update(self.bound)
|
||||
self.parent.globals.update(self.globals)
|
||||
else:
|
||||
# TODO(mdan): This is not accurate.
|
||||
self.parent.read.update(self.read - self.bound)
|
||||
@ -305,6 +305,11 @@ class ActivityAnalyzer(transformer.Base):
|
||||
self._exit_and_record_scope(node)
|
||||
return node
|
||||
|
||||
def visit_Global(self, node):
|
||||
for name in node.names:
|
||||
self.scope.globals.add(qual_names.QN(name))
|
||||
return node
|
||||
|
||||
def visit_Expr(self, node):
|
||||
return self._process_statement(node)
|
||||
|
||||
|
@ -541,6 +541,8 @@ class ActivityAnalyzerTest(ActivityAnalyzerTestBase):
|
||||
fn_node = node
|
||||
body_scope = anno.getanno(fn_node, NodeAnno.BODY_SCOPE)
|
||||
self.assertScopeIs(body_scope, ('global_b', 'c'), ('global_a',))
|
||||
self.assertSetEqual(body_scope.globals, set(
|
||||
(QN('global_a'), QN('global_b'))))
|
||||
|
||||
def test_class_definition_basic(self):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user