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