[Python-checkins] gh-105229: Remove syntactic support for super-instructions (#105703)

gvanrossum webhook-mailer at python.org
Mon Jun 12 13:47:15 EDT 2023


https://github.com/python/cpython/commit/b9e7dc797d71ce582fdb05be5a0e32d351f24bcb
commit: b9e7dc797d71ce582fdb05be5a0e32d351f24bcb
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2023-06-12T17:47:08Z
summary:

gh-105229: Remove syntactic support for super-instructions (#105703)

It will not be used again.

files:
M Tools/cases_generator/generate_cases.py
M Tools/cases_generator/parser.py

diff --git a/Tools/cases_generator/generate_cases.py b/Tools/cases_generator/generate_cases.py
index 49feb5048e59..69216c17ed87 100644
--- a/Tools/cases_generator/generate_cases.py
+++ b/Tools/cases_generator/generate_cases.py
@@ -390,7 +390,7 @@ def write_body(self, out: Formatter, dedent: int, cache_adjust: int = 0) -> None
         names_to_skip = self.unmoved_names | frozenset({UNUSED, "null"})
         offset = 0
         context = self.block.context
-        assert context != None
+        assert context is not None and context.owner is not None
         filename = context.owner.filename
         for line in self.block_text:
             out.set_lineno(self.block_line + offset, filename)
@@ -464,28 +464,14 @@ def write_body(self, out: Formatter, cache_adjust: int) -> None:
 
 
 @dataclasses.dataclass
-class SuperOrMacroInstruction:
-    """Common fields for super- and macro instructions."""
+class MacroInstruction:
+    """A macro instruction."""
 
     name: str
     stack: list[StackEffect]
     initial_sp: int
     final_sp: int
     instr_fmt: str
-
-
- at dataclasses.dataclass
-class SuperInstruction(SuperOrMacroInstruction):
-    """A super-instruction."""
-
-    super: parser.Super
-    parts: list[Component]
-
-
- at dataclasses.dataclass
-class MacroInstruction(SuperOrMacroInstruction):
-    """A macro instruction."""
-
     macro: parser.Macro
     parts: list[Component | parser.CacheEffect]
     predicted: bool = False
@@ -505,7 +491,7 @@ class OverriddenInstructionPlaceHolder:
     name: str
 
 
-AnyInstruction = Instruction | SuperInstruction | MacroInstruction
+AnyInstruction = Instruction | MacroInstruction
 INSTR_FMT_PREFIX = "INSTR_FMT_"
 
 
@@ -538,12 +524,9 @@ def error(self, msg: str, node: parser.Node) -> None:
         self.errors += 1
 
     everything: list[
-        parser.InstDef | parser.Super | parser.Macro |
-        parser.Pseudo | OverriddenInstructionPlaceHolder
+        parser.InstDef | parser.Macro | parser.Pseudo | OverriddenInstructionPlaceHolder
     ]
     instrs: dict[str, Instruction]  # Includes ops
-    supers: dict[str, parser.Super]
-    super_instrs: dict[str, SuperInstruction]
     macros: dict[str, parser.Macro]
     macro_instrs: dict[str, MacroInstruction]
     families: dict[str, parser.Family]
@@ -558,7 +541,6 @@ def parse(self) -> None:
 
         self.everything = []
         self.instrs = {}
-        self.supers = {}
         self.macros = {}
         self.families = {}
         self.pseudos = {}
@@ -571,7 +553,7 @@ def parse(self) -> None:
         files = " + ".join(self.input_filenames)
         print(
             f"Read {len(self.instrs)} instructions/ops, "
-            f"{len(self.supers)} supers, {len(self.macros)} macros, "
+            f"{len(self.macros)} macros, {len(self.pseudos)} pseudos, "
             f"and {len(self.families)} families from {files}",
             file=sys.stderr,
         )
@@ -605,7 +587,7 @@ def parse_file(self, filename: str, instrs_idx: dict[str, int]) -> None:
 
         # Parse from start
         psr.setpos(start)
-        thing: parser.InstDef | parser.Super | parser.Macro | parser.Family | None
+        thing: parser.InstDef | parser.Macro | parser.Family | None
         thing_first_token = psr.peek()
         while thing := psr.definition():
             match thing:
@@ -627,9 +609,6 @@ def parse_file(self, filename: str, instrs_idx: dict[str, int]) -> None:
                     self.instrs[name] = Instruction(thing)
                     instrs_idx[name] = len(self.everything)
                     self.everything.append(thing)
-                case parser.Super(name):
-                    self.supers[name] = thing
-                    self.everything.append(thing)
                 case parser.Macro(name):
                     self.macros[name] = thing
                     self.everything.append(thing)
@@ -648,7 +627,7 @@ def analyze(self) -> None:
 
         Raises SystemExit if there is an error.
         """
-        self.analyze_supers_and_macros_and_pseudos()
+        self.analyze_macros_and_pseudos()
         self.find_predictions()
         self.map_families()
         self.check_families()
@@ -656,7 +635,7 @@ def analyze(self) -> None:
     def find_predictions(self) -> None:
         """Find the instructions that need PREDICTED() labels."""
         for instr in self.instrs.values():
-            targets = set()
+            targets: set[str] = set()
             for line in instr.block_text:
                 if m := re.match(RE_PREDICTED, line):
                     targets.add(m.group(1))
@@ -760,33 +739,15 @@ def effect_counts(self, name: str) -> tuple[int, int, int]:
             assert False, f"Unknown instruction {name!r}"
         return cache, input, output
 
-    def analyze_supers_and_macros_and_pseudos(self) -> None:
-        """Analyze each super-, macro- and pseudo- instruction."""
-        self.super_instrs = {}
+    def analyze_macros_and_pseudos(self) -> None:
+        """Analyze each super- and macro instruction."""
         self.macro_instrs = {}
         self.pseudo_instrs = {}
-        for name, super in self.supers.items():
-            self.super_instrs[name] = self.analyze_super(super)
         for name, macro in self.macros.items():
             self.macro_instrs[name] = self.analyze_macro(macro)
         for name, pseudo in self.pseudos.items():
             self.pseudo_instrs[name] = self.analyze_pseudo(pseudo)
 
-    def analyze_super(self, super: parser.Super) -> SuperInstruction:
-        components = self.check_super_components(super)
-        stack, initial_sp = self.stack_analysis(components)
-        sp = initial_sp
-        parts: list[Component] = []
-        format = ""
-        for instr in components:
-            part, sp = self.analyze_instruction(instr, stack, sp)
-            parts.append(part)
-            format += instr.instr_fmt
-        final_sp = sp
-        return SuperInstruction(
-            super.name, stack, initial_sp, final_sp, format, super, parts
-        )
-
     def analyze_macro(self, macro: parser.Macro) -> MacroInstruction:
         components = self.check_macro_components(macro)
         stack, initial_sp = self.stack_analysis(components)
@@ -836,15 +797,6 @@ def analyze_instruction(
             sp += 1
         return Component(instr, input_mapping, output_mapping), sp
 
-    def check_super_components(self, super: parser.Super) -> list[Instruction]:
-        components: list[Instruction] = []
-        for op in super.ops:
-            if op.name not in self.instrs:
-                self.error(f"Unknown instruction {op.name!r}", super)
-            else:
-                components.append(self.instrs[op.name])
-        return components
-
     def check_macro_components(
         self, macro: parser.Macro
     ) -> list[InstructionOrCacheEffect]:
@@ -864,7 +816,7 @@ def check_macro_components(
     def stack_analysis(
         self, components: typing.Iterable[InstructionOrCacheEffect]
     ) -> tuple[list[StackEffect], int]:
-        """Analyze a super-instruction or macro.
+        """Analyze a macro.
 
         Ignore cache effects.
 
@@ -880,8 +832,8 @@ def stack_analysis(
                         # TODO: Eventually this will be needed, at least for macros.
                         self.error(
                             f"Instruction {instr.name!r} has variable-sized stack effect, "
-                            "which are not supported in super- or macro instructions",
-                            instr.inst,  # TODO: Pass name+location of super/macro
+                            "which are not supported in macro instructions",
+                            instr.inst,  # TODO: Pass name+location of macro
                         )
                     current -= len(instr.input_effects)
                     lowest = min(lowest, current)
@@ -901,7 +853,7 @@ def stack_analysis(
         return stack, -lowest
 
     def get_stack_effect_info(
-        self, thing: parser.InstDef | parser.Super | parser.Macro | parser.Pseudo
+        self, thing: parser.InstDef | parser.Macro | parser.Pseudo
     ) -> tuple[AnyInstruction | None, str, str]:
         def effect_str(effects: list[StackEffect]) -> str:
             if getattr(thing, "kind", None) == "legacy":
@@ -922,15 +874,6 @@ def effect_str(effects: list[StackEffect]) -> str:
                     instr = None
                     popped = ""
                     pushed = ""
-            case parser.Super():
-                instr = self.super_instrs[thing.name]
-                # TODO: Same as for Macro below, if needed.
-                popped = "+".join(
-                    effect_str(comp.instr.input_effects) for comp in instr.parts
-                )
-                pushed = "+".join(
-                    effect_str(comp.instr.output_effects) for comp in instr.parts
-                )
             case parser.Macro():
                 instr = self.macro_instrs[thing.name]
                 parts = [comp for comp in instr.parts if isinstance(comp, Component)]
@@ -1032,8 +975,6 @@ def write_metadata(self) -> None:
                     continue
                 case parser.InstDef():
                     format = self.instrs[thing.name].instr_fmt
-                case parser.Super():
-                    format = self.super_instrs[thing.name].instr_fmt
                 case parser.Macro():
                     format = self.macro_instrs[thing.name].instr_fmt
                 case parser.Pseudo():
@@ -1092,8 +1033,6 @@ def write_metadata(self) -> None:
                     case parser.InstDef():
                         if thing.kind != "op":
                             self.write_metadata_for_inst(self.instrs[thing.name])
-                    case parser.Super():
-                        self.write_metadata_for_super(self.super_instrs[thing.name])
                     case parser.Macro():
                         self.write_metadata_for_macro(self.macro_instrs[thing.name])
                     case parser.Pseudo():
@@ -1118,12 +1057,6 @@ def write_metadata_for_inst(self, instr: Instruction) -> None:
             f"    [{instr.name}] = {{ true, {INSTR_FMT_PREFIX}{instr.instr_fmt} }},"
         )
 
-    def write_metadata_for_super(self, sup: SuperInstruction) -> None:
-        """Write metadata for a super-instruction."""
-        self.out.emit(
-            f"    [{sup.name}] = {{ true, {INSTR_FMT_PREFIX}{sup.instr_fmt} }},"
-        )
-
     def write_metadata_for_macro(self, mac: MacroInstruction) -> None:
         """Write metadata for a macro-instruction."""
         self.out.emit(
@@ -1149,7 +1082,6 @@ def write_instructions(self) -> None:
 
             # Write and count instructions of all kinds
             n_instrs = 0
-            n_supers = 0
             n_macros = 0
             n_pseudos = 0
             for thing in self.everything:
@@ -1160,9 +1092,6 @@ def write_instructions(self) -> None:
                         if thing.kind != "op":
                             n_instrs += 1
                             self.write_instr(self.instrs[thing.name])
-                    case parser.Super():
-                        n_supers += 1
-                        self.write_super(self.super_instrs[thing.name])
                     case parser.Macro():
                         n_macros += 1
                         self.write_macro(self.macro_instrs[thing.name])
@@ -1172,8 +1101,8 @@ def write_instructions(self) -> None:
                         typing.assert_never(thing)
 
         print(
-            f"Wrote {n_instrs} instructions, {n_supers} supers, {n_macros}"
-            f" macros and {n_pseudos} pseudos to {self.output_filename}",
+            f"Wrote {n_instrs} instructions, {n_macros} macros, "
+            f"and {n_pseudos} pseudos to {self.output_filename}",
             file=sys.stderr,
         )
 
@@ -1197,23 +1126,10 @@ def write_instr(self, instr: Instruction) -> None:
                     self.out.emit("CHECK_EVAL_BREAKER();")
                 self.out.emit(f"DISPATCH();")
 
-    def write_super(self, sup: SuperInstruction) -> None:
-        """Write code for a super-instruction."""
-        with self.wrap_super_or_macro(sup):
-            first = True
-            for comp in sup.parts:
-                if not first:
-                    self.out.emit("oparg = (next_instr++)->op.arg;")
-                # self.out.emit("next_instr += OPSIZE(opcode) - 1;")
-                first = False
-                comp.write_body(self.out, 0)
-                if comp.instr.cache_offset:
-                    self.out.emit(f"next_instr += {comp.instr.cache_offset};")
-
     def write_macro(self, mac: MacroInstruction) -> None:
         """Write code for a macro instruction."""
         last_instr: Instruction | None = None
-        with self.wrap_super_or_macro(mac):
+        with self.wrap_macro(mac):
             cache_adjust = 0
             for part in mac.parts:
                 match part:
@@ -1239,30 +1155,29 @@ def write_macro(self, mac: MacroInstruction) -> None:
                 )
 
     @contextlib.contextmanager
-    def wrap_super_or_macro(self, up: SuperOrMacroInstruction):
-        """Shared boilerplate for super- and macro instructions."""
+    def wrap_macro(self, mac: MacroInstruction):
+        """Boilerplate for macro instructions."""
         # TODO: Somewhere (where?) make it so that if one instruction
         # has an output that is input to another, and the variable names
         # and types match and don't conflict with other instructions,
         # that variable is declared with the right name and type in the
         # outer block, rather than trusting the compiler to optimize it.
         self.out.emit("")
-        with self.out.block(f"TARGET({up.name})"):
-            match up:
-                case MacroInstruction(predicted=True, name=name):
-                    self.out.emit(f"PREDICTED({name});")
-            for i, var in reversed(list(enumerate(up.stack))):
+        with self.out.block(f"TARGET({mac.name})"):
+            if mac.predicted:
+                self.out.emit(f"PREDICTED({mac.name});")
+            for i, var in reversed(list(enumerate(mac.stack))):
                 src = None
-                if i < up.initial_sp:
-                    src = StackEffect(f"stack_pointer[-{up.initial_sp - i}]", "")
+                if i < mac.initial_sp:
+                    src = StackEffect(f"stack_pointer[-{mac.initial_sp - i}]", "")
                 self.out.declare(var, src)
 
             yield
 
-            # TODO: Use slices of up.stack instead of numeric values
-            self.out.stack_adjust(up.final_sp - up.initial_sp, [], [])
+            # TODO: Use slices of mac.stack instead of numeric values
+            self.out.stack_adjust(mac.final_sp - mac.initial_sp, [], [])
 
-            for i, var in enumerate(reversed(up.stack[: up.final_sp]), 1):
+            for i, var in enumerate(reversed(mac.stack[: mac.final_sp]), 1):
                 dst = StackEffect(f"stack_pointer[-{i}]", "")
                 self.out.assign(dst, var)
 
diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py
index 56920f23d750..2c75989a7e8a 100644
--- a/Tools/cases_generator/parser.py
+++ b/Tools/cases_generator/parser.py
@@ -118,12 +118,6 @@ class InstDef(Node):
     block: Block
 
 
- at dataclass
-class Super(Node):
-    name: str
-    ops: list[OpName]
-
-
 @dataclass
 class Macro(Node):
     name: str
@@ -144,11 +138,9 @@ class Pseudo(Node):
 
 class Parser(PLexer):
     @contextual
-    def definition(self) -> InstDef | Super | Macro | Family | Pseudo | None:
+    def definition(self) -> InstDef | Macro | Pseudo | Family | None:
         if inst := self.inst_def():
             return inst
-        if super := self.super_def():
-            return super
         if macro := self.macro_def():
             return macro
         if family := self.family_def():
@@ -287,25 +279,13 @@ def expression(self) -> Expression | None:
             return None
         return Expression(lx.to_text(tokens).strip())
 
-    @contextual
-    def super_def(self) -> Super | None:
-        if (tkn := self.expect(lx.IDENTIFIER)) and tkn.text == "super":
-            if self.expect(lx.LPAREN):
-                if tkn := self.expect(lx.IDENTIFIER):
-                    if self.expect(lx.RPAREN):
-                        if self.expect(lx.EQUALS):
-                            if ops := self.ops():
-                                self.require(lx.SEMI)
-                                res = Super(tkn.text, ops)
-                                return res
-
-    def ops(self) -> list[OpName] | None:
-        if op := self.op():
-            ops = [op]
-            while self.expect(lx.PLUS):
-                if op := self.op():
-                    ops.append(op)
-            return ops
+    # def ops(self) -> list[OpName] | None:
+    #     if op := self.op():
+    #         ops = [op]
+    #         while self.expect(lx.PLUS):
+    #             if op := self.op():
+    #                 ops.append(op)
+    #         return ops
 
     @contextual
     def op(self) -> OpName | None:
@@ -432,7 +412,7 @@ def c_blob(self) -> list[lx.Token]:
             src = sys.argv[2]
             filename = "<string>"
         else:
-            with open(filename) as f:
+            with open(filename, "r") as f:
                 src = f.read()
             srclines = src.splitlines()
             begin = srclines.index("// BEGIN BYTECODES //")



More information about the Python-checkins mailing list