Skip to content

Commit 0273a67

Browse files
committed
Merge branch 'feat/global-variables' into feat/integer-signedness
2 parents 6f48498 + d197a11 commit 0273a67

2 files changed

Lines changed: 7 additions & 29 deletions

File tree

‎pythonbpf/functions/functions_pass.py‎

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,10 @@ def handle_aug_assign(func, compilation_context, builder, stmt, local_sym_tab):
221221
f"cannot assign to '{name}': it is the context parameter"
222222
)
223223
elif name in compilation_context.bpf_globals:
224-
# Binding x anywhere in the body makes it local throughout, so this
225-
# statement reads an unbound local rather than the global. Python
226-
# raises UnboundLocalError; there is no runtime here in which to do
227-
# that, so the program is rejected.
224+
# `x += v` binds x as a local and reads it unbound: UnboundLocalError.
228225
raise SyntaxError(
229-
f"local variable '{name}' referenced before assignment: "
230-
f"'{name} += ...' binds '{name}' as a local, which shadows the "
231-
f"@bpfglobal of the same name, and reads it in the same "
232-
f"statement (Python raises UnboundLocalError here). Add "
233-
f"'global {name}' to update the global."
226+
f"local variable '{name}' referenced before assignment; "
227+
f"add 'global {name}' to update the @bpfglobal"
234228
)
235229
else:
236230
raise SyntaxError(f"augmented assignment to undefined variable '{name}'")
@@ -404,11 +398,6 @@ def process_stmt(
404398
elif isinstance(stmt, ast.AugAssign):
405399
handle_aug_assign(func, compilation_context, builder, stmt, local_sym_tab)
406400
elif isinstance(stmt, ast.Global):
407-
# Nothing to emit: `global x` binds a name for the whole function body,
408-
# so process_func_body collects every declaration before the first
409-
# statement is lowered (and before allocation, which would otherwise
410-
# give a declared name a stack slot). The branch exists so that a valid
411-
# declaration does not reach the unsupported-statement warning below.
412401
logger.debug(f"global declaration of {', '.join(stmt.names)} already bound")
413402
elif isinstance(stmt, ast.If):
414403
handle_if(func, compilation_context, builder, stmt, local_sym_tab)

‎pythonbpf/symbols.py‎

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,13 @@ class LocalSymbol(Symbol):
4242
shadows_global_from: int | None = None
4343

4444
def check_bound_at(self, name: str, lineno: int) -> None:
45-
"""Raise if `name` is read at `lineno` before its first binding.
46-
47-
Python's scoping is function-wide and static: assigning a name anywhere
48-
in a body makes it local everywhere in that body, so a read above the
49-
assignment is an UnboundLocalError rather than a read of the global.
50-
There is no runtime in which to raise that, so a program in this shape
51-
is rejected at compile time. The check applies only to locals that
52-
shadow a @bpfglobal, where staying silent would otherwise load an
53-
uninitialised slot from a name the author expected to be the global.
54-
"""
45+
"""Python's UnboundLocalError, at compile time: a local that shadows a
46+
@bpfglobal is unreadable above its binding. No-op for any other local."""
5547
if self.shadows_global_from is None or lineno > self.shadows_global_from:
5648
return
5749
raise SyntaxError(
58-
f"local variable '{name}' referenced before assignment: the "
59-
f"assignment on line {self.shadows_global_from} makes '{name}' a "
60-
f"local that shadows the @bpfglobal of the same name (Python "
61-
f"raises UnboundLocalError here). Add 'global {name}' if you meant "
62-
f"the global."
50+
f"local variable '{name}' referenced before its assignment on line "
51+
f"{self.shadows_global_from}; add 'global {name}' to use the @bpfglobal"
6352
)
6453

6554
def __iter__(self):

0 commit comments

Comments
 (0)