|
22 | 22 | # Instructions relying on a bit to modify its behavior. |
23 | 23 | # The lowest bit is used to encode custom behavior. |
24 | 24 | 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 | + ) |
30 | 36 | ) |
31 | 37 |
|
32 | 38 | BITFLAG2_OPCODES = (_opcode.opmap["LOAD_SUPER_ATTR"],) if PY312 else () |
|
49 | 55 | COMMON_CONSTANT_OPS = (_opcode.opmap["LOAD_COMMON_CONSTANT"],) if PY314 else () |
50 | 56 |
|
51 | 57 | # 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 |
53 | 58 | FORMAT_VALUE_OPS = ( |
54 | 59 | ( |
55 | 60 | _opcode.opmap["CONVERT_VALUE"], |
@@ -197,10 +202,10 @@ class FormatValue(enum.IntEnum): |
197 | 202 | class SpecialMethod(enum.IntEnum): |
198 | 203 | """Special method names used with LOAD_SPECIAL""" |
199 | 204 |
|
200 | | - __ENTER__ = 0 |
201 | | - __EXIT__ = 1 |
202 | | - __AENTER__ = 2 |
203 | | - __AEXIT__ = 3 |
| 205 | + ENTER = 0 |
| 206 | + EXIT = 1 |
| 207 | + AENTER = 2 |
| 208 | + AEXIT = 3 |
204 | 209 |
|
205 | 210 |
|
206 | 211 | @enum.unique |
@@ -720,6 +725,7 @@ def stack_effect(self, jump: Optional[bool] = None) -> int: |
720 | 725 | arg = None |
721 | 726 | # 3.11 where LOAD_GLOBAL arg encode whether or we push a null |
722 | 727 | # 3.12 does the same for LOAD_ATTR |
| 728 | + # 3.14 does this for BUILD_INTERPOLATION |
723 | 729 | elif self._opcode in BITFLAG_OPCODES and isinstance(self._arg, tuple): |
724 | 730 | assert len(self._arg) == 2 |
725 | 731 | arg = self._arg[0] |
@@ -914,7 +920,7 @@ def _check_arg(self, name: str, opcode: int, arg: InstrArg) -> None: |
914 | 920 | and isinstance(arg[1], str) |
915 | 921 | ): |
916 | 922 | raise TypeError( |
917 | | - "operation %s argument must be a tuple[bool, str], " |
| 923 | + "operation %s argument must be a tuple[bool, str | FormatValue], " |
918 | 924 | "got %s (value=%s)" % (name, type(arg).__name__, str(arg)) |
919 | 925 | ) |
920 | 926 |
|
@@ -1019,7 +1025,23 @@ def _check_arg(self, name: str, opcode: int, arg: InstrArg) -> None: |
1019 | 1025 | "CommonConstants, got %s" % (name, type(arg).__name__) |
1020 | 1026 | ) |
1021 | 1027 |
|
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 | + ) |
1023 | 1045 |
|
1024 | 1046 | elif opcode_has_argument(opcode): |
1025 | 1047 | _check_arg_int(arg, name) |
0 commit comments