Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
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
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'))
bc.name = name or ''
bc.append(Instr("RETURN_VALUE"))
fix_bytecode(bc)
# for each in (bc):
# print(each)
# print('++++++++++')
yield from wait(EVALUATED)
delay = []
delay_append = delay.append
if any(bc.freevars):
for each in bc.freevars:
if each not in ctx.local:
if each not in ctx.bc.freevars:
ctx.bc.freevars.append(each)
delay_append(
Instr(
'LOAD_CLOSURE',
FreeVar(each),
lineno=def_fun.lineno + 1))
else:
if each not in ctx.bc.cellvars:
ctx.bc.cellvars.append(each)
delay_append(
Instr(
'LOAD_CLOSURE',
CellVar(each),
lineno=def_fun.lineno + 1))
delay_append(
Instr(
"BUILD_TUPLE", arg=len(bc.freevars),
lineno=def_fun.lineno + 1))
bc.Instr("RETURN_VALUE"), #
])
elif i_name == "CALL_FUNCTION":
if USE_WORDCODE:
n_stack_args = i_arg
else:
n_stack_args = (i_arg & 0xFF) + 2 * ((i_arg >> 8) & 0xFF)
new_code.extend([ # func -> arg(0) -> arg(1) -> ... -> arg(n-1)
bc.Instr("BUILD_TUPLE", n_stack_args), # func -> argtuple
bc.Instr("LOAD_FAST", '_[inverter]'), # func -> argtuple -> inverter
bc.Instr("LOAD_ATTR", 'call_function'), # func -> argtuple -> invertfunc
bc.Instr("ROT_THREE"), # invertfunc -> func -> argtuple
bc.Instr("LOAD_CONST", i_arg), # invertfunc -> func -> argtuple -> argspec
bc.Instr("LOAD_FAST", '_[value]'), # invertfunc -> func -> argtuple -> argspec -> value
bc.Instr("CALL_FUNCTION", 0x0004), # retval
bc.Instr("RETURN_VALUE"), #
])
# We do not trace CALL_FUNCTION_KW and CALL_FUNCTION_EX since tracing and
# inverting only require to detect getattr and setattr both in this project
# and in traits-enaml. Those two are always called using the CALL_FUNCTION
# bytecode instruction.
elif i_name == "BINARY_SUBSCR":
new_code.extend([ # obj -> index
bc.Instr("LOAD_FAST", '_[inverter]'), # obj -> index -> inverter
bc.Instr("LOAD_ATTR", 'binary_subscr'), # obj -> index -> invertfunc
bc.Instr("ROT_THREE"), # invertfunc -> obj -> index
bc.Instr("LOAD_FAST", '_[value]'), # invertfunc -> obj -> index -> value
bc.Instr("CALL_FUNCTION", 0x0003), # retval
bc.Instr("RETURN_VALUE"), #
])
def _check_dictionary_defs(self):
new_instr = []
new_instr_ind = -1
for index, instr in enumerate(self.block):
if isinstance(instr, Instr) and instr.opcode == pyop.STORE_FAST:
for dictionary in self.container_method.dictionary_defs:
if dictionary.name == instr.arg:
new_instr_ind = index
for index, item in enumerate(dictionary.keys):
# load the value
new_instr += self._ast_to_instr(dictionary.values[index], instr.lineno)
# load the dict
new_instr.append(Instr("LOAD_FAST", arg=instr.arg, lineno=instr.lineno))
# load the key
new_instr += self._ast_to_instr(dictionary.keys[index], instr.lineno)
new_instr.append(Instr("STORE_SUBSCR", lineno=instr.lineno))
self.container_method.dictionary_defs.remove(dictionary)
if new_instr_ind > -1:
self.updated_blocklist = self.updated_blocklist[0:new_instr_ind + 1] + new_instr + self.updated_blocklist[new_instr_ind + 1:]
def __init__(self, instruction, expression, index, fallback_ln):
self.instruction = instruction
self.expression = expression
self.index = index
self._methodname = None
self.jump_from = None
self.jump_target = None
self.jump_found = False
self.jump_from_addr = None
self.jump_to_addr = None
# self.jump_to_addr_abs = None
# self.jump_from_addr_abs = None
if isinstance(instruction, Label):
self.jump_target = instruction
self.instruction = Instr("NOP", lineno=fallback_ln)
elif isinstance(instruction.arg, Label):
self.jump_from = instruction.arg