Skip to content

Commit 987776e

Browse files
instr: properly handle instruction dealing with formatting and fix SpecialMethod enum
1 parent f31c09b commit 987776e

2 files changed

Lines changed: 48 additions & 15 deletions

File tree

src/bytecode/concrete.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
COMMON_CONSTANT_OPS,
3333
DUAL_ARG_OPCODES,
3434
DUAL_ARG_OPCODES_SINGLE_OPS,
35+
FORMAT_VALUE_OPS,
3536
INTRINSIC,
3637
INTRINSIC_1OP,
3738
INTRINSIC_2OP,
@@ -43,6 +44,7 @@
4344
CellVar,
4445
CommonConstants,
4546
Compare,
47+
FormatValue,
4648
FreeVar,
4749
Instr,
4850
InstrArg,
@@ -1062,7 +1064,12 @@ def to_bytecode(
10621064
arg = locals_lookup[c_arg]
10631065
elif opcode in _opcode.hasname:
10641066
if opcode in BITFLAG_OPCODES:
1065-
arg = (bool(c_arg & 1), self.names[c_arg >> 1])
1067+
arg = (
1068+
bool(c_arg & 1),
1069+
FormatValue(c_arg >> 1)
1070+
if opcode in FORMAT_VALUE_OPS
1071+
else self.names[c_arg >> 1],
1072+
)
10661073
elif opcode in BITFLAG2_OPCODES:
10671074
arg = (bool(c_arg & 1), bool(c_arg & 2), self.names[c_arg >> 2])
10681075
else:
@@ -1328,9 +1335,13 @@ def concrete_instructions(self) -> None:
13281335
isinstance(arg, tuple)
13291336
and len(arg) == 2
13301337
and isinstance(arg[0], bool)
1331-
and isinstance(arg[1], str)
13321338
), arg
1333-
index = self.add(self.names, arg[1])
1339+
if isinstance(arg[1], str):
1340+
index = self.add(self.names, arg[1])
1341+
elif isinstance(arg, FormatValue):
1342+
index = int(arg)
1343+
else:
1344+
assert False, arg # noqa
13341345
c_arg = int(arg[0]) + (index << 1)
13351346
elif opcode in BITFLAG2_OPCODES:
13361347
assert (

src/bytecode/instr.py

Lines changed: 34 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,17 @@
2222
# Instructions relying on a bit to modify its behavior.
2323
# The lowest bit is used to encode custom behavior.
2424
BITFLAG_OPCODES = (
25-
(_opcode.opmap["LOAD_GLOBAL"], _opcode.opmap["LOAD_ATTR"])
26-
if PY312
27-
else (_opcode.opmap["LOAD_GLOBAL"],)
28-
if PY311
29-
else ()
25+
(
26+
_opcode.opmap["BUILD_INTERPOLATION"],
27+
_opcode.opmap["LOAD_GLOBAL"],
28+
_opcode.opmap["LOAD_ATTR"],
29+
)
30+
if PY314
31+
else (
32+
(_opcode.opmap["LOAD_GLOBAL"], _opcode.opmap["LOAD_ATTR"])
33+
if PY312
34+
else ((_opcode.opmap["LOAD_GLOBAL"],) if PY311 else ())
35+
)
3036
)
3137

3238
BITFLAG2_OPCODES = (_opcode.opmap["LOAD_SUPER_ATTR"],) if PY312 else ()
@@ -49,7 +55,6 @@
4955
COMMON_CONSTANT_OPS = (_opcode.opmap["LOAD_COMMON_CONSTANT"],) if PY314 else ()
5056

5157
# Value formatting related opcodes (only handle CONVERT_VALUE and BUILD_INTERPOLATION)
52-
# XXX BUILD_INTERPOLATION in 314 need a bit shift and has 2 args
5358
FORMAT_VALUE_OPS = (
5459
(
5560
_opcode.opmap["CONVERT_VALUE"],
@@ -197,10 +202,10 @@ class FormatValue(enum.IntEnum):
197202
class SpecialMethod(enum.IntEnum):
198203
"""Special method names used with LOAD_SPECIAL"""
199204

200-
__ENTER__ = 0
201-
__EXIT__ = 1
202-
__AENTER__ = 2
203-
__AEXIT__ = 3
205+
ENTER = 0
206+
EXIT = 1
207+
AENTER = 2
208+
AEXIT = 3
204209

205210

206211
@enum.unique
@@ -720,6 +725,7 @@ def stack_effect(self, jump: Optional[bool] = None) -> int:
720725
arg = None
721726
# 3.11 where LOAD_GLOBAL arg encode whether or we push a null
722727
# 3.12 does the same for LOAD_ATTR
728+
# 3.14 does this for BUILD_INTERPOLATION
723729
elif self._opcode in BITFLAG_OPCODES and isinstance(self._arg, tuple):
724730
assert len(self._arg) == 2
725731
arg = self._arg[0]
@@ -914,7 +920,7 @@ def _check_arg(self, name: str, opcode: int, arg: InstrArg) -> None:
914920
and isinstance(arg[1], str)
915921
):
916922
raise TypeError(
917-
"operation %s argument must be a tuple[bool, str], "
923+
"operation %s argument must be a tuple[bool, str | FormatValue], "
918924
"got %s (value=%s)" % (name, type(arg).__name__, str(arg))
919925
)
920926

@@ -1019,7 +1025,23 @@ def _check_arg(self, name: str, opcode: int, arg: InstrArg) -> None:
10191025
"CommonConstants, got %s" % (name, type(arg).__name__)
10201026
)
10211027

1022-
# XXX format value handling
1028+
elif opcode in FORMAT_VALUE_OPS:
1029+
if opcode in BITFLAG_OPCODES:
1030+
if not (
1031+
isinstance(arg, tuple)
1032+
and len(arg) == 2
1033+
and isinstance(arg[0], bool)
1034+
and isinstance(arg[1], FormatValue)
1035+
):
1036+
raise TypeError(
1037+
"operation %s argument must be a tuple[bool, FormatValue], "
1038+
"got %s (value=%s)" % (name, type(arg).__name__, str(arg))
1039+
)
1040+
elif not isinstance(arg, FormatValue):
1041+
raise TypeError(
1042+
"operation %s argument must be a FormatValue] "
1043+
"got %s (value=%s)" % (name, type(arg).__name__, str(arg))
1044+
)
10231045

10241046
elif opcode_has_argument(opcode):
10251047
_check_arg_int(arg, name)

0 commit comments

Comments
 (0)