cinderx 2026.1.16.2__cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- __static__/__init__.py +641 -0
- __static__/compiler_flags.py +8 -0
- __static__/enum.py +160 -0
- __static__/native_utils.py +77 -0
- __static__/type_code.py +48 -0
- __strict__/__init__.py +39 -0
- _cinderx.so +0 -0
- cinderx/__init__.py +577 -0
- cinderx/__pycache__/__init__.cpython-314.pyc +0 -0
- cinderx/_asyncio.py +156 -0
- cinderx/compileall.py +710 -0
- cinderx/compiler/__init__.py +40 -0
- cinderx/compiler/__main__.py +137 -0
- cinderx/compiler/config.py +7 -0
- cinderx/compiler/consts.py +72 -0
- cinderx/compiler/debug.py +70 -0
- cinderx/compiler/dis_stable.py +283 -0
- cinderx/compiler/errors.py +151 -0
- cinderx/compiler/flow_graph_optimizer.py +1287 -0
- cinderx/compiler/future.py +91 -0
- cinderx/compiler/misc.py +32 -0
- cinderx/compiler/opcode_cinder.py +18 -0
- cinderx/compiler/opcode_static.py +100 -0
- cinderx/compiler/opcodebase.py +158 -0
- cinderx/compiler/opcodes.py +991 -0
- cinderx/compiler/optimizer.py +547 -0
- cinderx/compiler/pyassem.py +3711 -0
- cinderx/compiler/pycodegen.py +7660 -0
- cinderx/compiler/pysourceloader.py +62 -0
- cinderx/compiler/static/__init__.py +1404 -0
- cinderx/compiler/static/compiler.py +629 -0
- cinderx/compiler/static/declaration_visitor.py +335 -0
- cinderx/compiler/static/definite_assignment_checker.py +280 -0
- cinderx/compiler/static/effects.py +160 -0
- cinderx/compiler/static/module_table.py +666 -0
- cinderx/compiler/static/type_binder.py +2176 -0
- cinderx/compiler/static/types.py +10580 -0
- cinderx/compiler/static/util.py +81 -0
- cinderx/compiler/static/visitor.py +91 -0
- cinderx/compiler/strict/__init__.py +69 -0
- cinderx/compiler/strict/class_conflict_checker.py +249 -0
- cinderx/compiler/strict/code_gen_base.py +409 -0
- cinderx/compiler/strict/common.py +507 -0
- cinderx/compiler/strict/compiler.py +352 -0
- cinderx/compiler/strict/feature_extractor.py +130 -0
- cinderx/compiler/strict/flag_extractor.py +97 -0
- cinderx/compiler/strict/loader.py +827 -0
- cinderx/compiler/strict/preprocessor.py +11 -0
- cinderx/compiler/strict/rewriter/__init__.py +5 -0
- cinderx/compiler/strict/rewriter/remove_annotations.py +84 -0
- cinderx/compiler/strict/rewriter/rewriter.py +975 -0
- cinderx/compiler/strict/runtime.py +77 -0
- cinderx/compiler/symbols.py +1754 -0
- cinderx/compiler/unparse.py +414 -0
- cinderx/compiler/visitor.py +194 -0
- cinderx/jit.py +230 -0
- cinderx/opcode.py +202 -0
- cinderx/static.py +113 -0
- cinderx/strictmodule.py +6 -0
- cinderx/test_support.py +341 -0
- cinderx-2026.1.16.2.dist-info/METADATA +15 -0
- cinderx-2026.1.16.2.dist-info/RECORD +68 -0
- cinderx-2026.1.16.2.dist-info/WHEEL +6 -0
- cinderx-2026.1.16.2.dist-info/licenses/LICENSE +21 -0
- cinderx-2026.1.16.2.dist-info/top_level.txt +5 -0
- opcodes/__init__.py +0 -0
- opcodes/assign_opcode_numbers.py +272 -0
- opcodes/cinderx_opcodes.py +121 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Portions copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
# pyre-strict
|
|
3
|
+
|
|
4
|
+
"""Parser for future statements"""
|
|
5
|
+
|
|
6
|
+
import ast
|
|
7
|
+
|
|
8
|
+
from .visitor import ASTVisitor
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FutureParser(ASTVisitor):
|
|
12
|
+
features = (
|
|
13
|
+
"nested_scopes",
|
|
14
|
+
"generators",
|
|
15
|
+
"division",
|
|
16
|
+
"absolute_import",
|
|
17
|
+
"with_statement",
|
|
18
|
+
"print_function",
|
|
19
|
+
"unicode_literals",
|
|
20
|
+
"generator_stop",
|
|
21
|
+
"barry_as_FLUFL",
|
|
22
|
+
"annotations",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.valid: set[ast.ImportFrom] = set()
|
|
28
|
+
self.found_features: set[str] = set()
|
|
29
|
+
self.possible_docstring = True
|
|
30
|
+
|
|
31
|
+
def visitModule(self, node: ast.Module) -> None:
|
|
32
|
+
for s in node.body:
|
|
33
|
+
if (
|
|
34
|
+
self.possible_docstring
|
|
35
|
+
and isinstance(s, ast.Expr)
|
|
36
|
+
and isinstance(s.value, ast.Constant)
|
|
37
|
+
and isinstance(s.value.value, str)
|
|
38
|
+
):
|
|
39
|
+
self.possible_docstring = False
|
|
40
|
+
continue
|
|
41
|
+
# no docstring after first statement
|
|
42
|
+
self.possible_docstring = False
|
|
43
|
+
if not self.check_stmt(s):
|
|
44
|
+
break
|
|
45
|
+
|
|
46
|
+
def check_stmt(self, stmt: ast.stmt) -> bool:
|
|
47
|
+
if isinstance(stmt, ast.ImportFrom) and stmt.module == "__future__":
|
|
48
|
+
for alias in stmt.names:
|
|
49
|
+
name = alias.name
|
|
50
|
+
if name in self.features:
|
|
51
|
+
self.found_features.add(name)
|
|
52
|
+
elif name == "braces":
|
|
53
|
+
raise SyntaxError("not a chance")
|
|
54
|
+
else:
|
|
55
|
+
raise SyntaxError("future feature %s is not defined" % name)
|
|
56
|
+
self.valid.add(stmt)
|
|
57
|
+
return True
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
def get_features(self) -> set[str]:
|
|
61
|
+
"""Return set of features enabled by future statements"""
|
|
62
|
+
return self.found_features
|
|
63
|
+
|
|
64
|
+
def get_valid(self) -> set[ast.ImportFrom]:
|
|
65
|
+
"""Return set of valid future statements"""
|
|
66
|
+
return self.valid
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class BadFutureParser(ASTVisitor):
|
|
70
|
+
"""Check for invalid future statements"""
|
|
71
|
+
|
|
72
|
+
def __init__(self, valid_parser: FutureParser) -> None:
|
|
73
|
+
super().__init__()
|
|
74
|
+
self.valid_parser = valid_parser
|
|
75
|
+
|
|
76
|
+
def visitImportFrom(self, node: ast.ImportFrom) -> None:
|
|
77
|
+
if node.module != "__future__":
|
|
78
|
+
return
|
|
79
|
+
if node in self.valid_parser.get_valid():
|
|
80
|
+
return
|
|
81
|
+
raise SyntaxError(
|
|
82
|
+
"from __future__ imports must occur at the beginning of the file"
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def find_futures(node: ast.AST) -> set[str]:
|
|
87
|
+
p1 = FutureParser()
|
|
88
|
+
p2 = BadFutureParser(p1)
|
|
89
|
+
p1.visit(node)
|
|
90
|
+
p2.visit(node)
|
|
91
|
+
return p1.get_features()
|
cinderx/compiler/misc.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Portions copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
# pyre-strict
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
MANGLE_LEN = 256 # magic constant from compile.c
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def mangle(name: str, klass: str | None) -> str:
|
|
9
|
+
if klass is None:
|
|
10
|
+
return name
|
|
11
|
+
if not name.startswith("__"):
|
|
12
|
+
return name
|
|
13
|
+
if len(name) + 2 >= MANGLE_LEN:
|
|
14
|
+
return name
|
|
15
|
+
# TODO: Probably need to split and mangle recursively?
|
|
16
|
+
if "." in name:
|
|
17
|
+
return name
|
|
18
|
+
if name.endswith("__"):
|
|
19
|
+
return name
|
|
20
|
+
try:
|
|
21
|
+
i = 0
|
|
22
|
+
while klass[i] == "_":
|
|
23
|
+
i = i + 1
|
|
24
|
+
except IndexError:
|
|
25
|
+
return name
|
|
26
|
+
klass = klass[i:]
|
|
27
|
+
|
|
28
|
+
tlen = len(klass) + len(name)
|
|
29
|
+
if tlen > MANGLE_LEN:
|
|
30
|
+
klass = klass[: MANGLE_LEN - tlen]
|
|
31
|
+
|
|
32
|
+
return "_{}{}".format(klass, name)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
# pyre-strict
|
|
3
|
+
|
|
4
|
+
from .opcodebase import Opcode
|
|
5
|
+
from .opcodes import opcode as base_opcode
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
opcode: Opcode = base_opcode.copy()
|
|
9
|
+
opcode.def_op("LOAD_METHOD_SUPER", 198)
|
|
10
|
+
opcode.hasconst.add("LOAD_SUPER_METHOD")
|
|
11
|
+
opcode.def_op("LOAD_ATTR_SUPER", 199)
|
|
12
|
+
opcode.hasconst.add("LOAD_ATTR_SUPER")
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
opcode.stack_effects.update(
|
|
16
|
+
LOAD_METHOD_SUPER=-1,
|
|
17
|
+
LOAD_ATTR_SUPER=-2,
|
|
18
|
+
)
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
|
|
3
|
+
# pyre-strict
|
|
4
|
+
|
|
5
|
+
from .opcode_cinder import opcode as opcode_cinder
|
|
6
|
+
from .opcodebase import Opcode
|
|
7
|
+
|
|
8
|
+
opcode: Opcode = opcode_cinder.copy()
|
|
9
|
+
opcode.def_op("INVOKE_METHOD", 158)
|
|
10
|
+
opcode.hasconst.add("INVOKE_METHOD")
|
|
11
|
+
opcode.def_op("LOAD_FIELD", 159)
|
|
12
|
+
opcode.hasconst.add("LOAD_FIELD")
|
|
13
|
+
opcode.def_op("STORE_FIELD", 166)
|
|
14
|
+
opcode.hasconst.add("STORE_FIELD")
|
|
15
|
+
opcode.def_op("BUILD_CHECKED_LIST", 168)
|
|
16
|
+
opcode.hasconst.add("BUILD_CHECKED_LIST")
|
|
17
|
+
opcode.def_op("LOAD_TYPE", 169)
|
|
18
|
+
opcode.hasconst.add("LOAD_TYPE")
|
|
19
|
+
opcode.def_op("CAST", 170)
|
|
20
|
+
opcode.hasconst.add("CAST")
|
|
21
|
+
opcode.def_op("LOAD_LOCAL", 171)
|
|
22
|
+
opcode.hasconst.add("LOAD_LOCAL")
|
|
23
|
+
opcode.def_op("STORE_LOCAL", 172)
|
|
24
|
+
opcode.hasconst.add("STORE_LOCAL")
|
|
25
|
+
opcode.def_op("PRIMITIVE_BOX", 174)
|
|
26
|
+
opcode.jabs_op("POP_JUMP_IF_ZERO", 175)
|
|
27
|
+
opcode.jabs_op("POP_JUMP_IF_NONZERO", 176)
|
|
28
|
+
opcode.def_op("PRIMITIVE_UNBOX", 177)
|
|
29
|
+
opcode.def_op("PRIMITIVE_BINARY_OP", 178)
|
|
30
|
+
opcode.def_op("PRIMITIVE_UNARY_OP", 179)
|
|
31
|
+
opcode.def_op("PRIMITIVE_COMPARE_OP", 180)
|
|
32
|
+
opcode.def_op("LOAD_ITERABLE_ARG", 181)
|
|
33
|
+
opcode.def_op("LOAD_MAPPING_ARG", 182)
|
|
34
|
+
opcode.def_op("INVOKE_FUNCTION", 183)
|
|
35
|
+
opcode.hasconst.add("INVOKE_FUNCTION")
|
|
36
|
+
opcode.jabs_op("JUMP_IF_ZERO_OR_POP", 184)
|
|
37
|
+
opcode.jabs_op("JUMP_IF_NONZERO_OR_POP", 185)
|
|
38
|
+
opcode.def_op("FAST_LEN", 186)
|
|
39
|
+
opcode.def_op("CONVERT_PRIMITIVE", 187)
|
|
40
|
+
opcode.def_op("INVOKE_NATIVE", 189)
|
|
41
|
+
opcode.hasconst.add("INVOKE_NATIVE")
|
|
42
|
+
opcode.def_op("LOAD_CLASS", 190)
|
|
43
|
+
opcode.hasconst.add("LOAD_CLASS")
|
|
44
|
+
opcode.def_op("BUILD_CHECKED_MAP", 191)
|
|
45
|
+
opcode.hasconst.add("BUILD_CHECKED_MAP")
|
|
46
|
+
opcode.def_op("SEQUENCE_GET", 192)
|
|
47
|
+
opcode.def_op("SEQUENCE_SET", 193)
|
|
48
|
+
opcode.def_op("LIST_DEL", 194)
|
|
49
|
+
opcode.def_op("REFINE_TYPE", 195)
|
|
50
|
+
opcode.hasconst.add("REFINE_TYPE")
|
|
51
|
+
opcode.def_op("PRIMITIVE_LOAD_CONST", 196)
|
|
52
|
+
opcode.hasconst.add("PRIMITIVE_LOAD_CONST")
|
|
53
|
+
opcode.def_op("RETURN_PRIMITIVE", 197)
|
|
54
|
+
opcode.def_op("TP_ALLOC", 200)
|
|
55
|
+
opcode.hasconst.add("TP_ALLOC")
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _load_mapping_arg_effect(oparg: int, _jmp: int = 0) -> int:
|
|
59
|
+
if oparg == 2:
|
|
60
|
+
return -1
|
|
61
|
+
elif oparg == 3:
|
|
62
|
+
return -2
|
|
63
|
+
return 1
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
opcode.stack_effects.update(
|
|
67
|
+
INVOKE_METHOD=lambda oparg, jmp: -(oparg[1] + 1),
|
|
68
|
+
LOAD_METHOD_STATIC=1,
|
|
69
|
+
LOAD_FIELD=0,
|
|
70
|
+
STORE_FIELD=-2,
|
|
71
|
+
CAST=0,
|
|
72
|
+
LOAD_LOCAL=1,
|
|
73
|
+
STORE_LOCAL=-1,
|
|
74
|
+
PRIMITIVE_BOX=0,
|
|
75
|
+
POP_JUMP_IF_ZERO=-1,
|
|
76
|
+
POP_JUMP_IF_NONZERO=-1,
|
|
77
|
+
PRIMITIVE_UNBOX=0,
|
|
78
|
+
PRIMITIVE_BINARY_OP=lambda oparg, jmp: -1,
|
|
79
|
+
PRIMITIVE_UNARY_OP=lambda oparg, jmp: 0,
|
|
80
|
+
PRIMITIVE_COMPARE_OP=lambda oparg, jmp: -1,
|
|
81
|
+
LOAD_ITERABLE_ARG=1,
|
|
82
|
+
LOAD_MAPPING_ARG=_load_mapping_arg_effect,
|
|
83
|
+
INVOKE_FUNCTION=lambda oparg, jmp=0: (-oparg[1]) + 1,
|
|
84
|
+
INVOKE_NATIVE=lambda oparg, jmp=0: (-len(oparg[1])) + 2,
|
|
85
|
+
JUMP_IF_ZERO_OR_POP=lambda oparg, jmp=0: 0 if jmp else -1,
|
|
86
|
+
JUMP_IF_NONZERO_OR_POP=lambda oparg, jmp=0: 0 if jmp else -1,
|
|
87
|
+
FAST_LEN=0,
|
|
88
|
+
CONVERT_PRIMITIVE=0,
|
|
89
|
+
LOAD_CLASS=1,
|
|
90
|
+
BUILD_CHECKED_MAP=lambda oparg, jmp: 1 - 2 * oparg[1],
|
|
91
|
+
SEQUENCE_GET=-1,
|
|
92
|
+
SEQUENCE_SET=-3,
|
|
93
|
+
LIST_DEL=-2,
|
|
94
|
+
REFINE_TYPE=0,
|
|
95
|
+
PRIMITIVE_LOAD_CONST=1,
|
|
96
|
+
RETURN_PRIMITIVE=-1,
|
|
97
|
+
TP_ALLOC=1,
|
|
98
|
+
BUILD_CHECKED_LIST=lambda oparg, jmp: 1 - oparg[1],
|
|
99
|
+
LOAD_TYPE=0,
|
|
100
|
+
)
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
2
|
+
# pyre-strict
|
|
3
|
+
from typing import Callable
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Opcode:
|
|
7
|
+
CMP_OP = (
|
|
8
|
+
"<",
|
|
9
|
+
"<=",
|
|
10
|
+
"==",
|
|
11
|
+
"!=",
|
|
12
|
+
">",
|
|
13
|
+
">=",
|
|
14
|
+
"BAD",
|
|
15
|
+
)
|
|
16
|
+
CONTAINS_OP_ARGS = (
|
|
17
|
+
"in",
|
|
18
|
+
"not in",
|
|
19
|
+
)
|
|
20
|
+
IS_OP_ARGS = (
|
|
21
|
+
"is",
|
|
22
|
+
"is not",
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
HAVE_ARGUMENT = 90 # Opcodes from here have an argument:
|
|
26
|
+
EXTENDED_ARG = 144
|
|
27
|
+
EXTENDED_OPCODE = 126
|
|
28
|
+
CODEUNIT_SIZE = 2
|
|
29
|
+
|
|
30
|
+
def __init__(self) -> None:
|
|
31
|
+
self.hasconst: set[str] = set()
|
|
32
|
+
self.hasname: set[int] = set()
|
|
33
|
+
self.hasjrel: set[int] = set()
|
|
34
|
+
self.hasjabs: set[int] = set()
|
|
35
|
+
self.haslocal: set[int] = set()
|
|
36
|
+
self.hascompare: set[int] = set()
|
|
37
|
+
self.hasfree: set[int] = set()
|
|
38
|
+
self.shadowop: set[int] = set()
|
|
39
|
+
|
|
40
|
+
self.opmap: dict[str, int] = {}
|
|
41
|
+
self.opname: list[str] = ["<{!r}>".format(op) for op in range(256)]
|
|
42
|
+
self.stack_effects: dict[str, object] = {}
|
|
43
|
+
|
|
44
|
+
# New for 3.14, we need to know popped vs pushed for the load borrow analysis.
|
|
45
|
+
self.popped: dict[str, int | Callable[[object], int]] = {}
|
|
46
|
+
self.pushed: dict[str, int | Callable[[object], int]] = {}
|
|
47
|
+
|
|
48
|
+
def stack_effect(self, opcode: int, oparg, jump: int) -> int: # pyre-ignore[2]
|
|
49
|
+
oparg_int = 0
|
|
50
|
+
if opcode >= self.HAVE_ARGUMENT:
|
|
51
|
+
if oparg is None:
|
|
52
|
+
raise ValueError(
|
|
53
|
+
"stack_effect: opcode requires oparg but oparg was not specified"
|
|
54
|
+
)
|
|
55
|
+
oparg_int = int(oparg)
|
|
56
|
+
elif oparg is not None:
|
|
57
|
+
raise ValueError(
|
|
58
|
+
"stack_effect: opcode does not permit oparg but oparg was specified"
|
|
59
|
+
)
|
|
60
|
+
# pyre-fixme[6]: For 1st argument expected `Optional[bool]` but got `int`.
|
|
61
|
+
jump_int = {None: -1, True: 1, False: 0}.get(jump)
|
|
62
|
+
if jump_int is None:
|
|
63
|
+
raise ValueError("stack_effect: jump must be False, True or None")
|
|
64
|
+
opname = self.opname[opcode]
|
|
65
|
+
return self.stack_effect_raw(opname, oparg_int, jump_int)
|
|
66
|
+
|
|
67
|
+
def stack_effect_raw(self, opname: str, oparg, jump: int) -> int: # pyre-ignore[2]
|
|
68
|
+
effect = self.stack_effects.get(opname)
|
|
69
|
+
if effect is None:
|
|
70
|
+
raise ValueError(
|
|
71
|
+
f"Error, opcode {opname} was not found, please update opcode.stack_effects"
|
|
72
|
+
)
|
|
73
|
+
if isinstance(effect, int):
|
|
74
|
+
return effect
|
|
75
|
+
else:
|
|
76
|
+
return effect(oparg, jump) # pyre-ignore[29]
|
|
77
|
+
|
|
78
|
+
def get_num_popped(self, opname: str, oparg: object) -> int:
|
|
79
|
+
popped = self.popped.get(opname)
|
|
80
|
+
if popped is None:
|
|
81
|
+
raise ValueError(
|
|
82
|
+
f"Error, opcode {opname} was not found, please update opcode.stack_effects"
|
|
83
|
+
)
|
|
84
|
+
if isinstance(popped, int):
|
|
85
|
+
return popped
|
|
86
|
+
else:
|
|
87
|
+
return popped(oparg)
|
|
88
|
+
|
|
89
|
+
def get_num_pushed(self, opname: str, oparg: object) -> int:
|
|
90
|
+
pushed = self.pushed.get(opname)
|
|
91
|
+
if pushed is None:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"Error, opcode {opname} was not found, please update opcode.stack_effects"
|
|
94
|
+
)
|
|
95
|
+
if isinstance(pushed, int):
|
|
96
|
+
return pushed
|
|
97
|
+
else:
|
|
98
|
+
return pushed(oparg)
|
|
99
|
+
|
|
100
|
+
def def_op(self, name: str, op: int) -> None:
|
|
101
|
+
# Fill in any missing space in the opname list for
|
|
102
|
+
# opargs which are > 255.
|
|
103
|
+
while op >= len(self.opname):
|
|
104
|
+
self.opname.append("<{!r}>".format(op))
|
|
105
|
+
self.opname[op] = name
|
|
106
|
+
self.opmap[name] = op
|
|
107
|
+
setattr(self, name, op)
|
|
108
|
+
|
|
109
|
+
def name_op(self, name: str, op: int) -> None:
|
|
110
|
+
self.def_op(name, op)
|
|
111
|
+
self.hasname.add(op)
|
|
112
|
+
|
|
113
|
+
def jrel_op(self, name: str, op: int) -> None:
|
|
114
|
+
self.def_op(name, op)
|
|
115
|
+
self.hasjrel.add(op)
|
|
116
|
+
|
|
117
|
+
def jabs_op(self, name: str, op: int) -> None:
|
|
118
|
+
self.def_op(name, op)
|
|
119
|
+
self.hasjabs.add(op)
|
|
120
|
+
|
|
121
|
+
def has_jump(self, op: int) -> bool:
|
|
122
|
+
return op in self.hasjrel or op in self.hasjabs
|
|
123
|
+
|
|
124
|
+
def shadow_op(self, name: str, op: int) -> None:
|
|
125
|
+
self.def_op(name, op)
|
|
126
|
+
self.shadowop.add(op)
|
|
127
|
+
|
|
128
|
+
def remove_op(self, opname: str) -> None:
|
|
129
|
+
op = self.opmap[opname]
|
|
130
|
+
self.hasconst.discard(opname)
|
|
131
|
+
self.hasname.discard(op)
|
|
132
|
+
self.hasjrel.discard(op)
|
|
133
|
+
self.hasjabs.discard(op)
|
|
134
|
+
self.haslocal.discard(op)
|
|
135
|
+
self.hascompare.discard(op)
|
|
136
|
+
self.hasfree.discard(op)
|
|
137
|
+
self.shadowop.discard(op)
|
|
138
|
+
self.opmap.pop(opname)
|
|
139
|
+
self.opname[op] = None # pyre-ignore[6]
|
|
140
|
+
self.stack_effects.pop(opname)
|
|
141
|
+
delattr(self, opname)
|
|
142
|
+
|
|
143
|
+
def copy(self) -> "Opcode":
|
|
144
|
+
result = Opcode()
|
|
145
|
+
result.hasconst = self.hasconst.copy()
|
|
146
|
+
result.hasname = self.hasname.copy()
|
|
147
|
+
result.hasjrel = self.hasjrel.copy()
|
|
148
|
+
result.hasjabs = self.hasjabs.copy()
|
|
149
|
+
result.haslocal = self.haslocal.copy()
|
|
150
|
+
result.hascompare = self.hascompare.copy()
|
|
151
|
+
result.hasfree = self.hasfree.copy()
|
|
152
|
+
result.shadowop = self.shadowop.copy()
|
|
153
|
+
result.opmap = self.opmap.copy()
|
|
154
|
+
result.opname = self.opname.copy()
|
|
155
|
+
result.stack_effects = self.stack_effects.copy()
|
|
156
|
+
for name, op in self.opmap.items():
|
|
157
|
+
setattr(result, name, op)
|
|
158
|
+
return result
|