diff --git a/dev_scripts/cflow.py b/dev_scripts/cflow.py index bc965f6..fc37f34 100644 --- a/dev_scripts/cflow.py +++ b/dev_scripts/cflow.py @@ -72,7 +72,9 @@ def run(file: Path, out_dir: Path, version: PythonVersion, print=False): edit_pyc_lines(pyc, src_lines) cfts = {bc.codeobj: bc_to_cft(bc) for bc in pyc.iter_bytecodes()} - out_src = normalize_source(str(SourceContext(pyc, src_lines, cfts))) + out_src = (str(SourceContext(pyc, src_lines, cfts))) + try: out_src = normalize_source(out_src) + except: pass out_path = out_dir / "b.py" out_path.write_text(out_src, encoding="utf-8") @@ -158,8 +160,7 @@ def main(input: Path, output: str, version: PythonVersion, graph: str | None, pr results = run(input, o, version)[0] if results in [Result.CompileError, Result.Error]: print(results) - else: - print_diff(o / input.stem / "a.py", o / input.stem / "b.py") + print_diff(o / input.stem / "a.py", o / input.stem / "b.py") else: if not output: out_dir = get_unused(prefix / str(version) / input.stem) diff --git a/pylingual/control_flow_reconstruction/templates/Exception.py b/pylingual/control_flow_reconstruction/templates/Exception.py index 607fbfc..1fbadae 100644 --- a/pylingual/control_flow_reconstruction/templates/Exception.py +++ b/pylingual/control_flow_reconstruction/templates/Exception.py @@ -4,7 +4,7 @@ from typing import override from .Block import BlockTemplate from .Conditional import IfElse, IfThen from ..cft import ControlFlowTemplate, EdgeCategory, EdgeKind, InstTemplate, SourceLine, SourceContext, register_template -from ..utils import E, N, T, condense_mapping, defer_source_to, ending_instructions, exact_instructions, no_back_edges, revert_on_fail, starting_instructions, to_indented_source, make_try_match, versions_from +from ..utils import E, N, T, condense_mapping, defer_source_to, ending_instructions, exact_instructions, no_back_edges, revert_on_fail, starting_instructions, to_indented_source, make_try_match, versions_from, hook_template reraise = +N().with_cond(exact_instructions("COPY", "POP_EXCEPT", "RERAISE")) @@ -20,6 +20,18 @@ class Except3_11(ControlFlowTemplate): if x := BareExcept3_11.try_match(cfg, node): return x +class Except3_10(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_10.try_match(cfg, node): + return x + if x := BareExcept3_10.try_match(cfg, node): + return x + if isinstance(node, Except3_10): + return node @register_template(0, 0, *versions_from(3, 12)) class Try3_12(ControlFlowTemplate): @@ -87,7 +99,106 @@ class TryElse3_12(ControlFlowTemplate): else: {try_else} """ +@register_template(0, 0, *versions_from(3, 10)) +class Try3_10(ControlFlowTemplate): + template = T( + try_header=N("try_body"), + try_body=N("try_footer.", None, "except_body"), + try_footer=N("tail."), + except_body=N("tail."), + tail=N.tail(), + ) + try_match = revert_on_fail( + make_try_match( + { + EdgeKind.Fall: "tail", + }, + "try_header", + "try_body", + "except_body", + "try_footer", + ) + ) + + @to_indented_source + def to_indented_source(): + """ + {try_header} + try: + {try_body} + {except_body} + """ + +class ExcBody3_10(ControlFlowTemplate): + @classmethod + @override + def try_match(cls, cfg, node) -> ControlFlowTemplate | None: + if x := NamedExc3_10.try_match(cfg, node): + return x + return node + +class NamedExc3_10(ExcBody3_10): + template = T( + STORE=N("body", None, "reraise").with_cond(exact_instructions("POP_TOP", "STORE_FAST", "POP_TOP", "SETUP_FINALLY")), + body=N("tail.", None, "cleanup"), + cleanup=N(E.exc("reraise")).with_cond(exact_instructions("POP_EXCEPT", "LOAD_CONST", "STORE_FAST", "DELETE_FAST", "LOAD_CONST", "RETURN_VALUE")), + reraise=reraise, + tail=N.tail(), + ) + + try_match = make_try_match({EdgeKind.Fall: "tail", EdgeKind.Exception: "reraise"}, "STORE", "body", "cleanup") + + to_indented_source = defer_source_to("body") + + +# @register_template(0, 0, *versions_from(3, 10)) +class BareExcept3_10(Except3_10): + template = T( + except_body=N("tail.", None).of_type(BlockTemplate), + tail=N.tail(), + ) + + try_match = make_try_match( + { + EdgeKind.Fall: "tail", + }, + "except_body", + ) + + @to_indented_source + def to_indented_source(): + """ + except: + {except_body} + """ + +@register_template(0, 0, *versions_from(3, 10)) +class ExceptExc3_10(Except3_10): + template = T( + except_header = N("body", "falsejump"), + body = N("tail."), + falsejump = N("tail.").of_subtemplate(ExcBody3_10), + tail = N.tail(), + ) + + try_match = make_try_match( + { + EdgeKind.Fall: "tail", + #EdgeKind.Exception: "reraise", + }, + "body", + "except_header", + "falsejump", + ) + + @to_indented_source + def to_indented_source(): + """ + {except_header} + {body} + {falsejump} + """ class BareExcept3_11(Except3_11): template = T(