Skip to content

Commit 40e624c

Browse files
authored
Merge pull request #31 from leamingrad/remove-repeated-set-creations
Optimisation: Avoid set copies when compiling files
2 parents a040791 + a9d5d69 commit 40e624c

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

src/fluent_compiler/codegen.py

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -116,20 +116,26 @@ def __init__(self, parent_scope=None):
116116
self._properties = {}
117117
self._assignments = {}
118118

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
124131

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
130134

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)
133139

134140
def reserve_name(self, requested, function_arg=False, is_builtin=False, properties=None):
135141
"""
@@ -146,10 +152,10 @@ def _add(final):
146152
return final
147153

148154
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)
151157
return _add(requested)
152-
if requested in self.all_reserved_names():
158+
if self.is_name_reserved(requested):
153159
raise AssertionError(f"Cannot use '{requested}' as argument name as it is already in use")
154160

155161
cleaned = cleanup_name(requested)
@@ -159,16 +165,20 @@ def _add(final):
159165
# To avoid shadowing of global names in local scope, we
160166
# take into account parent scope when assigning names.
161167

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):
170179
attempt = cleaned + str(count)
171180
count += 1
181+
172182
return _add(attempt)
173183

174184
def reserve_function_arg_name(self, name):
@@ -180,7 +190,7 @@ def reserve_function_arg_name(self, name):
180190
# To keep things simple, and the generated code predictable, we reserve
181191
# names for all function arguments in a separate scope, and insist on
182192
# the exact names
183-
if name in self.all_reserved_names():
193+
if self.is_name_reserved(name):
184194
raise AssertionError(f"Can't reserve '{name}' as function arg name as it is already reserved")
185195
self._function_arg_reserved_names.add(name)
186196

@@ -307,7 +317,7 @@ def add_assignment(self, name, value, allow_multiple=False):
307317
308318
x = value
309319
"""
310-
if name not in self.scope.names_in_use():
320+
if not self.scope.is_name_in_use(name):
311321
raise AssertionError(f"Cannot assign to unreserved name '{name}'")
312322

313323
if self.scope.has_assignment(name):
@@ -366,7 +376,7 @@ def __init__(self, name, args=None, parent_scope=None, source=None):
366376
if args is None:
367377
args = ()
368378
for arg in args:
369-
if arg in self.names_in_use():
379+
if self.is_name_in_use(arg):
370380
raise AssertionError(f"Can't use '{arg}' as function argument name because it shadows other names")
371381
self.reserve_name(arg, function_arg=True)
372382
self.args = args
@@ -663,7 +673,7 @@ class VariableReference(Expression):
663673
child_elements = []
664674

665675
def __init__(self, name, scope):
666-
if name not in scope.names_in_use():
676+
if not scope.is_name_in_use(name):
667677
raise AssertionError(f"Cannot refer to undefined variable '{name}'")
668678
self.name = name
669679
self.type = scope.get_name_properties(name).get(PROPERTY_TYPE, UNKNOWN_TYPE)
@@ -684,7 +694,7 @@ class FunctionCall(Expression):
684694
child_elements = ["args", "kwargs"]
685695

686696
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):
688698
raise AssertionError(f"Cannot call unknown function '{function_name}'")
689699
self.function_name = function_name
690700
self.args = list(args)

tests/test_codegen.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def test_reserve_name_function_arg(self):
6565
scope.reserve_function_arg_name("arg_name")
6666
scope.reserve_name("myfunc")
6767
func = codegen.Function("myfunc", args=["arg_name"], parent_scope=scope)
68-
self.assertNotIn("arg_name2", func.all_reserved_names())
68+
self.assertFalse(func.is_name_reserved("arg_name2"))
6969

7070
def test_reserve_name_nested(self):
7171
parent = codegen.Scope()

0 commit comments

Comments
 (0)