From ffe570a14a1212f12edf87cb4c1ca505c7de9dc5 Mon Sep 17 00:00:00 2001 From: serge-sans-paille Date: Sun, 8 Dec 2024 15:21:08 +0100 Subject: [PATCH] Fix interaction between static if and nested loop / function Fix #2263 --- pythran/tests/test_none.py | 25 +++++++++++++++++++ .../transformations/normalize_static_if.py | 18 ++++++++----- 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/pythran/tests/test_none.py b/pythran/tests/test_none.py index 822433ac0..9caec6872 100644 --- a/pythran/tests/test_none.py +++ b/pythran/tests/test_none.py @@ -467,6 +467,31 @@ def none_loop_break_continue_or_ret(n): return s''' self.run_test(code, 7, none_loop_break_continue_or_ret=[int]) + def test_none_loop_break_nested(self): + code = ''' + def none_loop_break_nested(n): + x = [None if i%2 else 1 for i in range(n)] + s = 3 + for j in x: + if j is None: + for k in x: + s += 1 + continue + else: + s += 1 + return s''' + self.run_test(code, 7, none_loop_break_nested=[int]) + + def test_none_nested_function(self): + code = ''' + def none_nested_function(a): + if a is None: + return 1 + def bar(x): + return [x] + return bar(a)[0]''' + self.run_test(code, 7, none_nested_function=[int]) + def test_none_operators0(self): code = ''' def helper(x): diff --git a/pythran/transformations/normalize_static_if.py b/pythran/transformations/normalize_static_if.py index 0b29d157a..6ce351593 100644 --- a/pythran/transformations/normalize_static_if.py +++ b/pythran/transformations/normalize_static_if.py @@ -47,7 +47,7 @@ def outline(name, formal_parameters, out_parameters, stmts, ) if has_return: pr = PatchReturn(stmts[-1], has_break or has_cont) - pr.visit(fdef) + pr.generic_visit(fdef) if has_break or has_cont: if not has_return: @@ -55,7 +55,7 @@ def outline(name, formal_parameters, out_parameters, stmts, stmts[-1].value], ast.Load()) pbc = PatchBreakContinue(stmts[-1]) - pbc.visit(fdef) + pbc.generic_visit(fdef) return fdef @@ -66,6 +66,9 @@ def __init__(self, guard, has_break_or_cont): self.guard = guard self.has_break_or_cont = has_break_or_cont + def visit_FunctionDef(self, node): + return node + def visit_Return(self, node): if node is self.guard: holder = "StaticIfNoReturn" @@ -92,11 +95,14 @@ class PatchBreakContinue(ast.NodeTransformer): def __init__(self, guard): self.guard = guard - def visit_For(self, _): - pass + def visit_FunctionDef(self, node): + return node + + def visit_For(self, node): + return node - def visit_While(self, _): - pass + def visit_While(self, node): + return node def patch_Control(self, node, flag): new_node = deepcopy(self.guard)