mirror of
https://github.com/python/cpython.git
synced 2025-08-30 21:48:47 +00:00
gh-105481: Generate the opcode lists in dis from data extracted from bytecodes.c (#106758)
This commit is contained in:
parent
3535ef1eec
commit
40f3f11a77
16 changed files with 402 additions and 158 deletions
|
@ -7,16 +7,7 @@ _opcode = import_module("_opcode")
|
|||
from _opcode import stack_effect
|
||||
|
||||
|
||||
class OpcodeTests(unittest.TestCase):
|
||||
|
||||
def check_bool_function_result(self, func, ops, expected):
|
||||
for op in ops:
|
||||
if isinstance(op, str):
|
||||
op = dis.opmap[op]
|
||||
with self.subTest(opcode=op, func=func):
|
||||
self.assertIsInstance(func(op), bool)
|
||||
self.assertEqual(func(op), expected)
|
||||
|
||||
class OpListTests(unittest.TestCase):
|
||||
def test_invalid_opcodes(self):
|
||||
invalid = [-100, -1, 255, 512, 513, 1000]
|
||||
self.check_bool_function_result(_opcode.is_valid, invalid, False)
|
||||
|
@ -24,6 +15,9 @@ class OpcodeTests(unittest.TestCase):
|
|||
self.check_bool_function_result(_opcode.has_const, invalid, False)
|
||||
self.check_bool_function_result(_opcode.has_name, invalid, False)
|
||||
self.check_bool_function_result(_opcode.has_jump, invalid, False)
|
||||
self.check_bool_function_result(_opcode.has_free, invalid, False)
|
||||
self.check_bool_function_result(_opcode.has_local, invalid, False)
|
||||
self.check_bool_function_result(_opcode.has_exc, invalid, False)
|
||||
|
||||
def test_is_valid(self):
|
||||
names = [
|
||||
|
@ -36,43 +30,24 @@ class OpcodeTests(unittest.TestCase):
|
|||
opcodes = [dis.opmap[opname] for opname in names]
|
||||
self.check_bool_function_result(_opcode.is_valid, opcodes, True)
|
||||
|
||||
def test_has_arg(self):
|
||||
has_arg = ['SWAP', 'LOAD_FAST', 'INSTRUMENTED_POP_JUMP_IF_TRUE', 'JUMP']
|
||||
no_arg = ['SETUP_WITH', 'POP_TOP', 'NOP', 'CACHE']
|
||||
self.check_bool_function_result(_opcode.has_arg, has_arg, True)
|
||||
self.check_bool_function_result(_opcode.has_arg, no_arg, False)
|
||||
def test_oplists(self):
|
||||
def check_function(self, func, expected):
|
||||
for op in [-10, 520]:
|
||||
with self.subTest(opcode=op, func=func):
|
||||
res = func(op)
|
||||
self.assertIsInstance(res, bool)
|
||||
self.assertEqual(res, op in expected)
|
||||
|
||||
def test_has_const(self):
|
||||
has_const = ['LOAD_CONST', 'RETURN_CONST', 'KW_NAMES']
|
||||
no_const = ['SETUP_WITH', 'POP_TOP', 'NOP', 'CACHE']
|
||||
self.check_bool_function_result(_opcode.has_const, has_const, True)
|
||||
self.check_bool_function_result(_opcode.has_const, no_const, False)
|
||||
check_function(self, _opcode.has_arg, dis.hasarg)
|
||||
check_function(self, _opcode.has_const, dis.hasconst)
|
||||
check_function(self, _opcode.has_name, dis.hasname)
|
||||
check_function(self, _opcode.has_jump, dis.hasjump)
|
||||
check_function(self, _opcode.has_free, dis.hasfree)
|
||||
check_function(self, _opcode.has_local, dis.haslocal)
|
||||
check_function(self, _opcode.has_exc, dis.hasexc)
|
||||
|
||||
def test_has_name(self):
|
||||
has_name = ['STORE_NAME', 'DELETE_ATTR', 'STORE_GLOBAL', 'IMPORT_FROM',
|
||||
'LOAD_FROM_DICT_OR_GLOBALS']
|
||||
no_name = ['SETUP_WITH', 'POP_TOP', 'NOP', 'CACHE']
|
||||
self.check_bool_function_result(_opcode.has_name, has_name, True)
|
||||
self.check_bool_function_result(_opcode.has_name, no_name, False)
|
||||
|
||||
def test_has_jump(self):
|
||||
has_jump = ['FOR_ITER', 'JUMP_FORWARD', 'JUMP', 'POP_JUMP_IF_TRUE', 'SEND']
|
||||
no_jump = ['SETUP_WITH', 'POP_TOP', 'NOP', 'CACHE']
|
||||
self.check_bool_function_result(_opcode.has_jump, has_jump, True)
|
||||
self.check_bool_function_result(_opcode.has_jump, no_jump, False)
|
||||
|
||||
# the following test is part of the refactor, it will be removed soon
|
||||
def test_against_legacy_bool_values(self):
|
||||
# limiting to ops up to ENTER_EXECUTOR, because everything after that
|
||||
# is not currently categorized correctly in opcode.py.
|
||||
for op in range(0, opcode.opmap['ENTER_EXECUTOR']):
|
||||
with self.subTest(op=op):
|
||||
if opcode.opname[op] != f'<{op}>':
|
||||
self.assertEqual(op in dis.hasarg, _opcode.has_arg(op))
|
||||
self.assertEqual(op in dis.hasconst, _opcode.has_const(op))
|
||||
self.assertEqual(op in dis.hasname, _opcode.has_name(op))
|
||||
self.assertEqual(op in dis.hasjrel, _opcode.has_jump(op))
|
||||
|
||||
class OpListTests(unittest.TestCase):
|
||||
def test_stack_effect(self):
|
||||
self.assertEqual(stack_effect(dis.opmap['POP_TOP']), -1)
|
||||
self.assertEqual(stack_effect(dis.opmap['BUILD_SLICE'], 0), -1)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue