Merge branch 'cflow-refactor' into cflow-refactor

This commit is contained in:
drospierski24
2025-07-10 12:11:46 -05:00
committed by GitHub
5 changed files with 447 additions and 244 deletions
+2
View File
@@ -52,6 +52,8 @@ def edit_pyc_lines(pyc: PYCFile, src_lines: list[str]):
line_insts[0].starts_line = lno
for inst in line_insts[1:]:
inst.starts_line = None
if lno is not None and lno + 1 not in lno_bytecodes and pyc.version <= (3, 7) and src_lines[lno - 1].strip().startswith('@'):
bc.instructions[line_insts[0].offset // 2 + 1].starts_line = lno + 1
def run(file: Path, out_dir: Path, version: PythonVersion, print=False):
@@ -1,5 +1,5 @@
from ..cft import ControlFlowTemplate, EdgeKind, register_template
from ..utils import T, N, defer_source_to, run_is, starting_instructions, to_indented_source, make_try_match, without_top_level_instructions
from ..utils import T, N, defer_source_to, run_is, with_instructions, has_instval, starting_instructions, to_indented_source, make_try_match, without_top_level_instructions
@register_template(1, 40)
@@ -46,7 +46,7 @@ class IfThen(ControlFlowTemplate):
class Assertion(ControlFlowTemplate):
template = T(
assertion=~N("fail", "tail"),
fail=+N().with_cond(starting_instructions("LOAD_ASSERTION_ERROR")),
fail=+N().with_cond(starting_instructions("LOAD_ASSERTION_ERROR"), has_instval("LOAD_GLOBAL", argval = "AssertionError")),
tail=N.tail(),
)
@@ -295,6 +295,21 @@ class TryFinally3_11(ControlFlowTemplate):
return list(chain(s, self.line("finally:"), in_finally, after))
class Except3_9(ControlFlowTemplate):
@classmethod
@override
def try_match(cls, cfg, node) -> ControlFlowTemplate | None:
if [x.opname for x in node.get_instructions()] == ["RERAISE"]:
return node
if x := ExceptExc3_9.try_match(cfg, node):
return x
if x := BareExcept3_9.try_match(cfg, node):
return x
if isinstance(node, Except3_9):
return node
class Except3_9(ControlFlowTemplate):
@classmethod
@@ -531,7 +546,7 @@ class Except3_6(ControlFlowTemplate):
@classmethod
@override
def try_match(cls, cfg, node) -> ControlFlowTemplate | None:
if [x.opname for x in node.get_instructions()] == ["END_FINALLY"]:
if [x.opname for x in node.get_instructions()[:1]] == ["END_FINALLY"]:
return node
if x := ExceptExc3_6.try_match(cfg, node):
return x
@@ -544,7 +559,7 @@ class Except3_6(ControlFlowTemplate):
class Try3_6(ControlFlowTemplate):
template = T(
try_header=~N("try_body").with_cond(without_top_level_instructions("SETUP_WITH")),
try_body=N("try_footer", None, "except_body"),
try_body=N("try_footer.", None, "except_body"),
try_footer=~N("tail."),
except_body=~N("tail.").with_in_deg(1).of_subtemplate(Except3_6),
tail=N.tail(),
@@ -583,10 +598,10 @@ class ExcBody3_6(ControlFlowTemplate):
class NamedExc3_6(ExcBody3_6):
template = T(
header=~N("body", None).with_cond(starting_instructions("POP_TOP", "STORE_FAST"), with_instructions("POP_TOP", "STORE_NAME")),
header=~N("body", None).with_cond(with_instructions("POP_TOP", "STORE_FAST"), with_instructions("POP_TOP", "STORE_NAME")),
body=N("normal_cleanup.", None, "exception_cleanup"),
normal_cleanup=~N("exception_cleanup."),
exception_cleanup=~N("tail.").with_cond(with_instructions("LOAD_CONST", "STORE_FAST"), with_instructions("LOAD_CONST", "STORE_NAME")),
exception_cleanup=~N("tail.").with_cond(with_instructions("STORE_FAST", "DELETE_FAST"), with_instructions("STORE_NAME", "DELETE_NAME")),
tail=N.tail()
)
@@ -694,7 +709,7 @@ class ReturnFinally3_6(ControlFlowTemplate):
class BareExcept3_6(Except3_6):
template = T(
except_body=~N("tail."),
except_body=~N("tail.").with_cond(starting_instructions("POP_TOP", "POP_TOP", "POP_TOP")),
tail=~N.tail(),
)
@@ -763,4 +778,5 @@ class TryFinally3_6(ControlFlowTemplate):
after = []
return list(chain(header, self.line("try:"), body, self.line("finally:"), in_finally, after))
@@ -118,6 +118,17 @@ def has_incoming_edge_of_categories(*categories: str):
return False
return check
def has_instval(opname: str, argval : Any):
def check_instructions(cfg: CFG, node: ControlFlowTemplate | None) -> bool:
for x in node.get_instructions():
if x.opname == opname and x.argval == argval:
return True
return False
return check_instructions
def run_is(n: int):
def check_run(cfg: CFG, node: ControlFlowTemplate | None) -> bool:
return cfg.run == n
+410 -236
View File
@@ -1,216 +1,11 @@
def TryExcept():
def a_TryExcept():
try:
print(1)
except:
print(2)
print(3)
def TryExceptMulti():
try:
print(1)
except a:
print(2)
except b:
print(3)
except c:
print(4)
print(5)
def TryExceptMultiFallback():
try:
print(1)
except a:
print(2)
except b:
print(3)
except:
print(4)
print(5)
def TryExceptMultiNamed():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
except C as c:
print(4)
print(5)
def TryExceptMultiNamedFallback():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
except:
print(4)
print(5)
def TryExceptMultiNamedAndUnnamed():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
print(5)
def TryExceptElseBare():
try:
print(1)
except:
print(2)
else:
print(3)
print(4)
def TryExceptElseMulti():
try:
print(1)
except a:
print(2)
except b:
print(3)
else:
print(4)
print(5)
def TryExceptElseMultiFallback():
try:
print(1)
except a:
print(2)
except b:
print(3)
except:
print(4)
else:
print(5)
print(6)
def TryExceptElseNamed():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
else:
print(4)
print(5)
def TryExceptElseMultiNamedAndUnnamed():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
else:
print(5)
print(6)
def TryFinallyBare():
try:
print(1)
finally:
print(2)
print(3)
def TryExceptFinallyBare():
try:
print(1)
except:
print(2)
finally:
print(3)
print(4)
def TryExceptFinallyBareSpecific():
try:
print(1)
except a:
print(2)
finally:
print(3)
print(4)
def TryExceptMultiFinally():
try:
print(1)
except a:
print(2)
except b:
print(3)
finally:
print(4)
print(5)
def TryExceptMultiFallbackFinally():
try:
print(1)
except a:
print(2)
except:
print(3)
finally:
print(4)
print(5)
def TryExceptMultiNamedFinally():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
finally:
print(4)
print(5)
def TryExceptMultiNamedFallbackFinally():
try:
print(1)
except A as a:
print(2)
except:
print(3)
finally:
print(4)
print(5)
def TryExceptMultiNamedAndUnnamedFinally():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
finally:
print(5)
print(6)
def TryExceptElseFinallyBare():
try:
print(1)
except:
print(2)
else:
print(3)
finally:
print(4)
print(5)
def TryExceptBareNested():
def b_TryExceptBareNested():
try:
print(1)
except:
@@ -220,46 +15,41 @@ def TryExceptBareNested():
except:
print(4)
def TryExceptReturn():
try:
print(1)
return 2
except:
print(2)
def TryExceptRaise():
def b1_TryExceptBareNestedFallthrough():
try:
print(1)
except:
print(2)
raise Exc
def TryExceptRaiseNamed():
try:
print(1)
except A as a:
print(2)
raise Exc
def TryExceptBareNestedNamed():
try:
print(1)
except A as a:
print(2)
try:
print(3)
except:
print(4)
print(5)
def TryExceptReturnNamed():
def b2_TryExceptBareNestedEarlyFallthrough():
try:
print(1)
return 2
except A as a:
except:
print(2)
try:
print(3)
except:
print(4)
print(5)
def TryExceptBareNestedMulti():
def b3_TryExceptBareNestedDoubleFallthrough():
try:
print(1)
except:
print(2)
try:
print(3)
except:
print(4)
print(5)
print(6)
def c_TryExceptBareMultiNested():
try:
print(1)
except a:
@@ -275,7 +65,358 @@ def TryExceptBareNestedMulti():
except:
print(7)
def TryExceptReturnMulti():
def c1_TryExceptBareMultiNestedFallthrough():
try:
print(1)
except a:
print(2)
try:
print(3)
except:
print(4)
print(5)
except b:
print(6)
try:
print(7)
except:
print(8)
def c2_TryExceptBareMultiNestedFallthrough2():
try:
print(1)
except a:
print(2)
try:
print(3)
except:
print(4)
print(5)
except b:
print(6)
try:
print(7)
except:
print(8)
print(9)
def c3_TryExceptBareMultiNestedEarlyFallthrough():
try:
print(1)
except a:
print(2)
try:
print(3)
except:
print(4)
except b:
print(5)
try:
print(6)
except:
print(7)
print(8)
def c4_TryExceptBareMultiNestedAllFallthrough():
try:
print(1)
except a:
print(2)
try:
print(3)
except:
print(4)
print(5)
except b:
print(6)
try:
print(7)
except:
print(8)
print(9)
print(10)
def d_TryExceptBareNestedNamed():
try:
print(1)
except A as a:
print(2)
try:
print(3)
except:
print(4)
def d1_TryExceptBareNestedNamedFallthrough():
try:
print(1)
except A as a:
print(2)
try:
print(3)
except:
print(4)
print(5)
def d2_TryExceptBareNestedNamedEarlyFallthrough():
try:
print(1)
except A as a:
print(2)
try:
print(3)
except:
print(4)
print(5)
def d3_TryExceptBareNestedNamedDoubleFallthrough():
try:
print(1)
except A as a:
print(2)
try:
print(3)
except:
print(4)
print(5)
print(6)
def e_TryExceptElseBare():
try:
print(1)
except:
print(2)
else:
print(3)
print(4)
def f_TryExceptElseFinallyBare():
try:
print(1)
except:
print(2)
else:
print(3)
finally:
print(4)
print(5)
def g_TryExceptElseMulti():
try:
print(1)
except a:
print(2)
except b:
print(3)
else:
print(4)
print(5)
def h_TryExceptElseMultiFallback():
try:
print(1)
except a:
print(2)
except b:
print(3)
except:
print(4)
else:
print(5)
print(6)
def i_TryExceptElseMultiNamedAndUnnamed():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
else:
print(5)
print(6)
def j_TryExceptElseNamed():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
else:
print(4)
print(5)
def k_TryExceptFinallyBare():
try:
print(1)
except:
print(2)
finally:
print(3)
print(4)
def l_TryExceptFinallyBareSpecific():
try:
print(1)
except a:
print(2)
finally:
print(3)
print(4)
def m_TryExceptMulti():
try:
print(1)
except a:
print(2)
except b:
print(3)
except c:
print(4)
print(5)
def n_TryExceptMultiFallback():
try:
print(1)
except a:
print(2)
except b:
print(3)
except:
print(4)
print(5)
def o_TryExceptMultiFallbackFinally():
try:
print(1)
except a:
print(2)
except:
print(3)
finally:
print(4)
print(5)
def p_TryExceptMultiNamed():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
except C as c:
print(4)
print(5)
def q_TryExceptMultiNamedAndUnnamed():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
print(5)
def r_TryExceptMultiNamedAndUnnamedFinally():
try:
print(1)
except A as a:
print(2)
except b:
print(3)
except:
print(4)
finally:
print(5)
print(6)
def s_TryExceptMultiNamedFallback():
try:
print(1)
except A as a:
print(2)
except:
print(3)
print(4)
def t_TryExceptMultiNamedFallbackFinally():
try:
print(1)
except A as a:
print(2)
except:
print(3)
finally:
print(4)
print(5)
def u_TryExceptMultiNamedFinally():
try:
print(1)
except A as a:
print(2)
except B as b:
print(3)
finally:
print(4)
print(5)
def v_TryExceptMultiFinally():
try:
print(1)
except a:
print(2)
except b:
print(3)
finally:
print(4)
print(5)
def w_TryExceptRaise():
try:
print(1)
except:
print(2)
raise Exc
def x_TryExceptRaiseMulti():
try:
print(1)
except a:
print(2)
raise Exc
except b:
print(3)
raise Exc
def y_TryExceptRaiseNamed():
try:
print(1)
except A as a:
print(2)
raise Exc
def z_TryExceptReturn():
try:
print(1)
return 2
except:
print(2)
def z1_TryExceptReturn():
try:
print(1)
return 2
except:
print(2)
return 3
def aa_TryExceptReturnMulti():
try:
print(1)
return 2
@@ -284,10 +425,21 @@ def TryExceptReturnMulti():
except b:
print(3)
def TryExceptRaiseMulti():
def aa1_TryExceptReturnMulti():
try:
print(1)
return 2
except a:
print(2)
return 3
except b:
print(3)
def ab_TryExceptReturnNamed():
try:
print(1)
return 2
except A as a:
print(2)
raise Exc
except b:
@@ -382,3 +534,25 @@ def TryFinallyRaise():
raise Exception()
'''
def ab1_TryExceptReturnNamed():
try:
print(1)
return 2
except A as a:
print(2)
return 3
def ac_TryFinallyBareFallthrough():
try:
print(1)
finally:
print(2)
print(3)
def ad_TryFinallyBare():
try:
print(1)
finally:
print(2)