@@ -116,20 +116,26 @@ def __init__(self, parent_scope=None):
116
116
self ._properties = {}
117
117
self ._assignments = {}
118
118
119
- def names_in_use (self ):
120
- names = self .names
121
- if self .parent_scope is not None :
122
- names = names | self .parent_scope .names_in_use ()
123
- return names
119
+ def is_name_in_use (self , name : str ) -> bool :
120
+ if name in self .names :
121
+ return True
122
+
123
+ if self .parent_scope is None :
124
+ return False
125
+
126
+ return self .parent_scope .is_name_in_use (name )
127
+
128
+ def is_name_reserved_function_arg (self , name : str ) -> bool :
129
+ if name in self ._function_arg_reserved_names :
130
+ return True
124
131
125
- def function_arg_reserved_names (self ):
126
- names = self ._function_arg_reserved_names
127
- if self .parent_scope is not None :
128
- names = names | self .parent_scope .function_arg_reserved_names ()
129
- return names
132
+ if self .parent_scope is None :
133
+ return False
130
134
131
- def all_reserved_names (self ):
132
- return self .names_in_use () | self .function_arg_reserved_names ()
135
+ return self .parent_scope .is_name_reserved_function_arg (name )
136
+
137
+ def is_name_reserved (self , name : str ) -> bool :
138
+ return self .is_name_in_use (name ) or self .is_name_reserved_function_arg (name )
133
139
134
140
def reserve_name (self , requested , function_arg = False , is_builtin = False , properties = None ):
135
141
"""
@@ -146,10 +152,10 @@ def _add(final):
146
152
return final
147
153
148
154
if function_arg :
149
- if requested in self .function_arg_reserved_names ( ):
150
- assert requested not in self .names_in_use ( )
155
+ if self .is_name_reserved_function_arg ( requested ):
156
+ assert not self .is_name_in_use ( requested )
151
157
return _add (requested )
152
- if requested in self .all_reserved_names ( ):
158
+ if self .is_name_reserved ( requested ):
153
159
raise AssertionError (f"Cannot use '{ requested } ' as argument name as it is already in use" )
154
160
155
161
cleaned = cleanup_name (requested )
@@ -159,16 +165,20 @@ def _add(final):
159
165
# To avoid shadowing of global names in local scope, we
160
166
# take into account parent scope when assigning names.
161
167
162
- used = self .all_reserved_names ()
163
- # We need to also protect against using keywords ('class', 'def' etc.)
164
- # i.e. count all keywords as 'used'.
165
- # However, some builtins are also keywords (e.g. 'None'), and so
166
- # if a builtin is being reserved, don't check against the keyword list
167
- if not is_builtin :
168
- used = used | set (keyword .kwlist )
169
- while attempt in used :
168
+ def _is_name_allowed (name : str ) -> bool :
169
+ # We need to also protect against using keywords ('class', 'def' etc.)
170
+ # i.e. count all keywords as 'used'.
171
+ # However, some builtins are also keywords (e.g. 'None'), and so
172
+ # if a builtin is being reserved, don't check against the keyword list
173
+ if (not is_builtin ) and keyword .iskeyword (name ):
174
+ return False
175
+
176
+ return not self .is_name_reserved (name )
177
+
178
+ while not _is_name_allowed (attempt ):
170
179
attempt = cleaned + str (count )
171
180
count += 1
181
+
172
182
return _add (attempt )
173
183
174
184
def reserve_function_arg_name (self , name ):
@@ -180,7 +190,7 @@ def reserve_function_arg_name(self, name):
180
190
# To keep things simple, and the generated code predictable, we reserve
181
191
# names for all function arguments in a separate scope, and insist on
182
192
# the exact names
183
- if name in self .all_reserved_names ( ):
193
+ if self .is_name_reserved ( name ):
184
194
raise AssertionError (f"Can't reserve '{ name } ' as function arg name as it is already reserved" )
185
195
self ._function_arg_reserved_names .add (name )
186
196
@@ -307,7 +317,7 @@ def add_assignment(self, name, value, allow_multiple=False):
307
317
308
318
x = value
309
319
"""
310
- if name not in self .scope .names_in_use ( ):
320
+ if not self .scope .is_name_in_use ( name ):
311
321
raise AssertionError (f"Cannot assign to unreserved name '{ name } '" )
312
322
313
323
if self .scope .has_assignment (name ):
@@ -366,7 +376,7 @@ def __init__(self, name, args=None, parent_scope=None, source=None):
366
376
if args is None :
367
377
args = ()
368
378
for arg in args :
369
- if arg in self .names_in_use ( ):
379
+ if self .is_name_in_use ( arg ):
370
380
raise AssertionError (f"Can't use '{ arg } ' as function argument name because it shadows other names" )
371
381
self .reserve_name (arg , function_arg = True )
372
382
self .args = args
@@ -663,7 +673,7 @@ class VariableReference(Expression):
663
673
child_elements = []
664
674
665
675
def __init__ (self , name , scope ):
666
- if name not in scope .names_in_use ( ):
676
+ if not scope .is_name_in_use ( name ):
667
677
raise AssertionError (f"Cannot refer to undefined variable '{ name } '" )
668
678
self .name = name
669
679
self .type = scope .get_name_properties (name ).get (PROPERTY_TYPE , UNKNOWN_TYPE )
@@ -684,7 +694,7 @@ class FunctionCall(Expression):
684
694
child_elements = ["args" , "kwargs" ]
685
695
686
696
def __init__ (self , function_name , args , kwargs , scope , expr_type = UNKNOWN_TYPE ):
687
- if function_name not in scope .names_in_use ( ):
697
+ if not scope .is_name_in_use ( function_name ):
688
698
raise AssertionError (f"Cannot call unknown function '{ function_name } '" )
689
699
self .function_name = function_name
690
700
self .args = list (args )
0 commit comments