Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_bin_op_dont_optimize(self):
# 1 / 0
code = Bytecode([Instr('LOAD_CONST', 1),
Instr('LOAD_CONST', 0),
Instr('BINARY_TRUE_DIVIDE'),
Instr('POP_TOP'),
Instr('LOAD_CONST', None),
Instr('RETURN_VALUE')])
self.check_dont_optimize(code)
# 1 // 0
code = Bytecode([Instr('LOAD_CONST', 1),
Instr('LOAD_CONST', 0),
Instr('BINARY_FLOOR_DIVIDE'),
Instr('POP_TOP'),
Instr('LOAD_CONST', None),
Instr('RETURN_VALUE')])
self.check_dont_optimize(code)
if ary_num >= 4:
init_code.append(Instr('DUP_TOP'))
for i in range((ary_num - 2) // 2):
init_code.append(Instr('DUP_TOP_TWO'))
if ary_num % 2:
init_code.append(Instr('DUP_TOP'))
else:
for i in range(ary_num - 1):
init_code.append(Instr('DUP_TOP'))
for i in range(ary_num):
init_code.append(Instr("LOAD_FAST", args[i]))
init_code.append(Instr("LIST_APPEND", ary_num - i))
init_code.append(Instr('LOAD_CONST', None))
init_code.append(Instr('RETURN_VALUE'))
init_code.flags = CompilerFlags.OPTIMIZED | CompilerFlags.NEWLOCALS | CompilerFlags.NOFREE
namespace['__init__'] = get_func_from_code(init_code.to_code(), '__init__')
fmt = '{}({})'.format(name, ', '.join(f'{arg}={{!r}}' for arg in args))
str_code = Bytecode()
str_code.argcount = 1
str_code.argnames.append('self')
str_code.append(Instr('LOAD_CONST', fmt.format))
str_code.append(Instr('LOAD_FAST', 'self'))
str_code.append(Instr('CALL_FUNCTION_EX', 0))
str_code.append(Instr('RETURN_VALUE'))
str_code.flags = CompilerFlags.OPTIMIZED | CompilerFlags.NEWLOCALS | CompilerFlags.NOFREE
# convert to a bytecode object and remove the leading and
# trailing ops: STORE_NAME LOAD_CONST RETURN_VALUE
outer_ops = bc.Bytecode.from_code(code)[0:-3]
# the stack now looks like the following:
# ...
# ...
# LOAD_CONST (<code>)
# LOAD_CONST (qualified name)
# MAKE_FUCTION (num defaults) // TOS
# extract the inner code object which represents the actual
# function code and update its flags
inner = bc.Bytecode.from_code(outer_ops[-3].arg)
inner.flags ^= (inner.flags & bc.CompilerFlags.NEWLOCALS)
# On Python 3 all comprehensions use a function call. To avoid scoping
# issues the function call is run in the dynamic scope.
if has_defs:
run_in_dynamic_scope(inner, global_vars)
else:
rewrite_globals_access(inner, global_vars)
outer_ops[-3].arg = inner.to_code()
# inline the modified code ops into the code generator
cg.code_ops.extend(outer_ops)
</code>
getter_code.append(Instr('BINARY_SUBSCR'))
getter_code.append(Instr('RETURN_VALUE'))
getter_code.flags = CompilerFlags.OPTIMIZED | CompilerFlags.NEWLOCALS | CompilerFlags.NOFREE
getter_fn = property(get_func_from_code(getter_code.to_code(), k))
setter_code = Bytecode()
setter_code.filename = filepath
setter_code.argcount = 2
setter_code.argnames.extend(['self', 'value'])
setter_code.append(Instr('LOAD_FAST', 'value'))
setter_code.append(Instr('LOAD_FAST', 'self'))
setter_code.append(Instr('LOAD_CONST', i))
setter_code.append(Instr('STORE_SUBSCR'))
setter_code.append(Instr('LOAD_CONST', None))
setter_code.append(Instr('RETURN_VALUE'))
setter_code.flags = CompilerFlags.OPTIMIZED | CompilerFlags.NEWLOCALS | CompilerFlags.NOFREE
setter_fn = getter_fn.setter(get_func_from_code(setter_code.to_code(), k))
namespace[k] = setter_fn
init_code = Bytecode()
init_code.name = '__init__'
init_code.filename = filepath
ary_num = len(annotations)
args = list(annotations)
init_code.argcount = ary_num + 1
init_code.argnames.extend(['self', *args])
if ary_num:
init_code.append(Instr('LOAD_FAST', 'self'))
if ary_num >= 4:
init_code.append(Instr('DUP_TOP'))
for i in range((ary_num - 2) // 2):
Instr(2, 'JUMP_FORWARD', label),
Instr(4, 'LOAD_CONST', 7),
Instr(4, 'STORE_NAME', 'x')])
blocks[1].extend([Instr(4, 'LOAD_CONST', None),
Instr(4, 'RETURN_VALUE')])
bytecode = blocks.to_bytecode()
label = Label()
self.assertEqual(bytecode,
[Instr(1, 'LOAD_NAME', 'test'),
Instr(1, 'POP_JUMP_IF_FALSE', label),
Instr(2, 'LOAD_CONST', 5),
Instr(2, 'STORE_NAME', 'x'),
Instr(2, 'JUMP_FORWARD', label),
Instr(4, 'LOAD_CONST', 7),
Instr(4, 'STORE_NAME', 'x'),
label,
Instr(4, 'LOAD_CONST', None),
Instr(4, 'RETURN_VALUE')])
# FIXME: test other attributes
def test_not_jump_if_false(self):
# Replace UNARY_NOT+POP_JUMP_IF_FALSE with POP_JUMP_IF_TRUE
#
# if not x:
# y = 9
# y = 4
label = Label()
code = Bytecode([Instr('LOAD_NAME', 'x'),
Instr('UNARY_NOT'),
Instr('POP_JUMP_IF_FALSE', label),
Instr('LOAD_CONST', 9),
Instr('STORE_NAME', 'y'),
label,
Instr('LOAD_CONST', 4),
Instr('STORE_NAME', 'y')])
code = self.optimize_blocks(code)
label = Label()
self.check(code,
Instr('LOAD_NAME', 'x'),
Instr('POP_JUMP_IF_TRUE', label),
Instr('LOAD_CONST', 9),
Instr('STORE_NAME', 'y'),
label,
Instr('LOAD_CONST', 4),
Instr('STORE_NAME', 'y'))
def test_compare_op_unary_not(self):
# FIXME: use constants, not hardcoded values
for op, not_op in (
(6, 7), # in => not in
(7, 6), # not in => in
(8, 9), # is => is not
(9, 8),
):
code = Bytecode([Instr('LOAD_NAME', 'a'),
Instr('LOAD_NAME', 'b'),
Instr('COMPARE_OP', op),
Instr('UNARY_NOT'),
Instr('STORE_NAME', 'x')])
self.check(code,
Instr('LOAD_NAME', 'a'),
Instr('LOAD_NAME', 'b'),
Instr('COMPARE_OP', not_op),
Instr('STORE_NAME', 'x'))
# don't optimize:
# x = not (a and b is True)
label_instr5 = Label()
code = Bytecode([Instr('LOAD_NAME', 'a'),
Instr('JUMP_IF_FALSE_OR_POP', label_instr5),
Instr('LOAD_NAME', 'b'),
Instr('LOAD_CONST', True),
Instr('COMPARE_OP', 8),
label_instr5,
Instr('UNARY_NOT'),
Instr('STORE_NAME', 'x'),
Instr('LOAD_CONST', None),
blocks = BytecodeBlocks()
label = blocks.add_block().label
blocks[0].extend([Instr(1, 'LOAD_NAME', 'test'),
Instr(1, 'POP_JUMP_IF_FALSE', label),
Instr(2, 'LOAD_CONST', 5),
Instr(2, 'STORE_NAME', 'x'),
Instr(2, 'JUMP_FORWARD', label),
Instr(4, 'LOAD_CONST', 7),
Instr(4, 'STORE_NAME', 'x')])
blocks[1].extend([Instr(4, 'LOAD_CONST', None),
Instr(4, 'RETURN_VALUE')])
bytecode = blocks.to_bytecode()
label = Label()
self.assertEqual(bytecode,
[Instr(1, 'LOAD_NAME', 'test'),
Instr(1, 'POP_JUMP_IF_FALSE', label),
Instr(2, 'LOAD_CONST', 5),
Instr(2, 'STORE_NAME', 'x'),
Instr(2, 'JUMP_FORWARD', label),
Instr(4, 'LOAD_CONST', 7),
Instr(4, 'STORE_NAME', 'x'),
label,
Instr(4, 'LOAD_CONST', None),
Instr(4, 'RETURN_VALUE')])
# FIXME: test other attributes
Instr('STORE_NAME', 'y'))
# x, y, z = [a, b, c]
code = Bytecode([Instr('LOAD_NAME', 'a'),
Instr('LOAD_NAME', 'b'),
Instr('LOAD_NAME', 'c'),
Instr(build_list, 3),
Instr('UNPACK_SEQUENCE', 3),
Instr('STORE_NAME', 'x'),
Instr('STORE_NAME', 'y'),
Instr('STORE_NAME', 'z')])
self.check(code,
Instr('LOAD_NAME', 'a'),
Instr('LOAD_NAME', 'b'),
Instr('LOAD_NAME', 'c'),
Instr('ROT_THREE'),
Instr('ROT_TWO'),
Instr('STORE_NAME', 'x'),
Instr('STORE_NAME', 'y'),
Instr('STORE_NAME', 'z'))
def create_bytecode(self, source, function=False):
code = self.compile(source, function=function)
bytecode = Bytecode.from_code(code)
from bytecode.tests import dump_code
dump_code(bytecode, lineno=False)
#dump_code(bytecode)
bytecode = bytecode.to_bytecode_blocks()
if not function:
block = bytecode[-1]
if not(block[-2].name == "LOAD_CONST"
and block[-2].arg is None
and block[-1].name == "RETURN_VALUE"):
raise ValueError("unable to find implicit RETURN_VALUE : %s"
% block[-2:])
del block[-2:]
return bytecode