Author: Richard Plangger <planri...@gmail.com> Branch: py3.5-async Changeset: r86131:663016b57d78 Date: 2016-08-10 18:27 +0200 http://bitbucket.org/pypy/pypy/changeset/663016b57d78/
Log: some more translation issues that showed up diff --git a/pypy/interpreter/astcompiler/assemble.py.orig b/pypy/interpreter/astcompiler/assemble.py.orig deleted file mode 100644 --- a/pypy/interpreter/astcompiler/assemble.py.orig +++ /dev/null @@ -1,765 +0,0 @@ -"""Python control flow graph generation and bytecode assembly.""" - -import os -from rpython.rlib import rfloat -from rpython.rlib.objectmodel import specialize, we_are_translated - -from pypy.interpreter.astcompiler import ast, consts, misc, symtable -from pypy.interpreter.error import OperationError -from pypy.interpreter.pycode import PyCode -from pypy.tool import stdlib_opcode as ops - - -class StackDepthComputationError(Exception): - pass - - -class Instruction(object): - """Represents a single opcode.""" - - def __init__(self, opcode, arg=0): - self.opcode = opcode - self.arg = arg - self.lineno = 0 - self.has_jump = False - - def size(self): - """Return the size of bytes of this instruction when it is - encoded. - """ - if self.opcode >= ops.HAVE_ARGUMENT: - return (6 if self.arg > 0xFFFF else 3) - return 1 - - def jump_to(self, target, absolute=False): - """Indicate the target this jump instruction. - - The opcode must be a JUMP opcode. - """ - self.jump = (target, absolute) - self.has_jump = True - - def __repr__(self): - data = [ops.opname[self.opcode]] - template = "<%s" - if self.opcode >= ops.HAVE_ARGUMENT: - data.append(self.arg) - template += " %i" - if self.has_jump: - data.append(self.jump[0]) - template += " %s" - template += ">" - return template % tuple(data) - - -class Block(object): - """A basic control flow block. - - It has one entry point and several possible exit points. Its - instructions may be jumps to other blocks, or if control flow - reaches the end of the block, it continues to next_block. - """ - - marked = False - have_return = False - auto_inserted_return = False - - def __init__(self): - self.instructions = [] - self.next_block = None - - def _post_order_see(self, stack, nextblock): - if nextblock.marked == 0: - nextblock.marked = 1 - stack.append(nextblock) - - def post_order(self): - """Return this block and its children in post order. This means - that the graph of blocks is first cleaned up to ignore - back-edges, thus turning it into a DAG. Then the DAG is - linearized. For example: - - A --> B -\ => [A, D, B, C] - \-> D ---> C - """ - resultblocks = [] - stack = [self] - self.marked = 1 - while stack: - current = stack[-1] - if current.marked == 1: - current.marked = 2 - if current.next_block is not None: - self._post_order_see(stack, current.next_block) - else: - i = current.marked - 2 - assert i >= 0 - while i < len(current.instructions): - instr = current.instructions[i] - i += 1 - if instr.has_jump: - current.marked = i + 2 - self._post_order_see(stack, instr.jump[0]) - break - else: - resultblocks.append(current) - stack.pop() - resultblocks.reverse() - return resultblocks - - def code_size(self): - """Return the encoded size of all the instructions in this - block. - """ - i = 0 - for instr in self.instructions: - i += instr.size() - return i - - def get_code(self): - """Encode the instructions in this block into bytecode.""" - code = [] - for instr in self.instructions: - opcode = instr.opcode - if opcode >= ops.HAVE_ARGUMENT: - arg = instr.arg - if instr.arg > 0xFFFF: - ext = arg >> 16 - code.append(chr(ops.EXTENDED_ARG)) - code.append(chr(ext & 0xFF)) - code.append(chr(ext >> 8)) - arg &= 0xFFFF - code.append(chr(opcode)) - code.append(chr(arg & 0xFF)) - code.append(chr(arg >> 8)) - else: - code.append(chr(opcode)) - return ''.join(code) - - -def _make_index_dict_filter(syms, flag): - i = 0 - result = {} - for name, scope in syms.iteritems(): - if scope == flag: - result[name] = i - i += 1 - return result - - -@specialize.argtype(0) -def _iter_to_dict(iterable, offset=0): - result = {} - index = offset - for item in iterable: - result[item] = index - index += 1 - return result - - -class PythonCodeMaker(ast.ASTVisitor): - """Knows how to assemble a PyCode object.""" - - def __init__(self, space, name, first_lineno, scope, compile_info): - self.space = space - self.name = name - self.first_lineno = first_lineno - self.compile_info = compile_info - self.first_block = self.new_block() - self.use_block(self.first_block) - self.names = {} - self.var_names = _iter_to_dict(scope.varnames) - self.cell_vars = _make_index_dict_filter(scope.symbols, - symtable.SCOPE_CELL) - self.free_vars = _iter_to_dict(scope.free_vars, len(self.cell_vars)) - self.w_consts = space.newdict() - self.argcount = 0 - self.kwonlyargcount = 0 - self.lineno_set = False - self.lineno = 0 - self.add_none_to_final_return = True - - def new_block(self): - return Block() - - def use_block(self, block): - """Start emitting bytecode into block.""" - self.current_block = block - self.instrs = block.instructions - - def use_next_block(self, block=None): - """Set this block as the next_block for the last and use it.""" - if block is None: - block = self.new_block() - self.current_block.next_block = block - self.use_block(block) - return block - - def is_dead_code(self): - """Return False if any code can be meaningfully added to the - current block, or True if it would be dead code.""" - # currently only True after a RETURN_VALUE. - return self.current_block.have_return - - def emit_op(self, op): - """Emit an opcode without an argument.""" - instr = Instruction(op) - if not self.lineno_set: - instr.lineno = self.lineno - self.lineno_set = True - if not self.is_dead_code(): - self.instrs.append(instr) - if op == ops.RETURN_VALUE: - self.current_block.have_return = True - return instr - - def emit_op_arg(self, op, arg): - """Emit an opcode with an integer argument.""" - instr = Instruction(op, arg) - if not self.lineno_set: - instr.lineno = self.lineno - self.lineno_set = True - if not self.is_dead_code(): - self.instrs.append(instr) - - def emit_op_name(self, op, container, name): - """Emit an opcode referencing a name.""" - self.emit_op_arg(op, self.add_name(container, name)) - - def emit_jump(self, op, block_to, absolute=False): - """Emit a jump opcode to another block.""" - self.emit_op(op).jump_to(block_to, absolute) - - def add_name(self, container, name): - """Get the index of a name in container.""" - name = self.scope.mangle(name) - try: - index = container[name] - except KeyError: - index = len(container) - container[name] = index - return index - - def add_const(self, obj): - """Add a W_Root to the constant array and return its location.""" - space = self.space - # To avoid confusing equal but separate types, we hash store the type - # of the constant in the dictionary. Moreover, we have to keep the - # difference between -0.0 and 0.0 floats, and this recursively in - # tuples. - w_key = self._make_key(obj) - - w_len = space.finditem(self.w_consts, w_key) - if w_len is None: - w_len = space.len(self.w_consts) - space.setitem(self.w_consts, w_key, w_len) - if space.int_w(w_len) == 0: - self.scope.doc_removable = False - return space.int_w(w_len) - - def _make_key(self, obj): - # see the tests 'test_zeros_not_mixed*' in ../test/test_compiler.py - space = self.space - w_type = space.type(obj) - if space.is_w(w_type, space.w_float): - val = space.float_w(obj) - if val == 0.0 and rfloat.copysign(1., val) < 0: - w_key = space.newtuple([obj, space.w_float, space.w_None]) - else: - w_key = space.newtuple([obj, space.w_float]) - elif space.is_w(w_type, space.w_complex): - w_real = space.getattr(obj, space.wrap("real")) - w_imag = space.getattr(obj, space.wrap("imag")) - real = space.float_w(w_real) - imag = space.float_w(w_imag) - real_negzero = (real == 0.0 and - rfloat.copysign(1., real) < 0) - imag_negzero = (imag == 0.0 and - rfloat.copysign(1., imag) < 0) - if real_negzero and imag_negzero: - tup = [obj, space.w_complex, space.w_None, space.w_None, - space.w_None] - elif imag_negzero: - tup = [obj, space.w_complex, space.w_None, space.w_None] - elif real_negzero: - tup = [obj, space.w_complex, space.w_None] - else: - tup = [obj, space.w_complex] - w_key = space.newtuple(tup) - elif space.is_w(w_type, space.w_tuple): - result_w = [obj, w_type] - for w_item in space.fixedview(obj): - result_w.append(self._make_key(w_item)) - w_key = space.newtuple(result_w[:]) - elif isinstance(obj, PyCode): - w_key = space.newtuple([obj, w_type, space.id(obj)]) - else: - w_key = space.newtuple([obj, w_type]) - return w_key - - def load_const(self, obj): - index = self.add_const(obj) - self.emit_op_arg(ops.LOAD_CONST, index) - - def update_position(self, lineno, force=False): - """Possibly change the lineno for the next instructions.""" - if force or lineno > self.lineno: - self.lineno = lineno - self.lineno_set = False - - def _resolve_block_targets(self, blocks): - """Compute the arguments of jump instructions.""" - last_extended_arg_count = 0 - # The reason for this loop is extended jumps. EXTENDED_ARG - # extends the bytecode size, so it might invalidate the offsets - # we've already given. Thus we have to loop until the number of - # extended args is stable. Any extended jump at all is - # extremely rare, so performance is not too concerning. - while True: - extended_arg_count = 0 - offset = 0 - force_redo = False - # Calculate the code offset of each block. - for block in blocks: - block.offset = offset - offset += block.code_size() - for block in blocks: - offset = block.offset - for instr in block.instructions: - offset += instr.size() - if instr.has_jump: - target, absolute = instr.jump - op = instr.opcode - # Optimize an unconditional jump going to another - # unconditional jump. - if op == ops.JUMP_ABSOLUTE or op == ops.JUMP_FORWARD: - if target.instructions: - target_op = target.instructions[0].opcode - if target_op == ops.JUMP_ABSOLUTE: - target = target.instructions[0].jump[0] - instr.opcode = ops.JUMP_ABSOLUTE - absolute = True - elif target_op == ops.RETURN_VALUE: - # Replace JUMP_* to a RETURN into - # just a RETURN - instr.opcode = ops.RETURN_VALUE - instr.arg = 0 - instr.has_jump = False - # The size of the code changed, - # we have to trigger another pass - force_redo = True - continue - if absolute: - jump_arg = target.offset - else: - jump_arg = target.offset - offset - instr.arg = jump_arg - if jump_arg > 0xFFFF: - extended_arg_count += 1 - if (extended_arg_count == last_extended_arg_count and - not force_redo): - break - else: - last_extended_arg_count = extended_arg_count - - def _build_consts_array(self): - """Turn the applevel constants dictionary into a list.""" - w_consts = self.w_consts - space = self.space - consts_w = [space.w_None] * space.len_w(w_consts) - w_iter = space.iter(w_consts) - first = space.wrap(0) - while True: - try: - w_key = space.next(w_iter) - except OperationError as e: - if not e.match(space, space.w_StopIteration): - raise - break - w_index = space.getitem(w_consts, w_key) - w_constant = space.getitem(w_key, first) - w_constant = misc.intern_if_common_string(space, w_constant) - consts_w[space.int_w(w_index)] = w_constant - return consts_w - - def _get_code_flags(self): - """Get an extra flags that should be attached to the code object.""" - raise NotImplementedError - - def _stacksize(self, blocks): - """Compute co_stacksize.""" - for block in blocks: - block.initial_depth = 0 - # Assumes that it is sufficient to walk the blocks in 'post-order'. - # This means we ignore all back-edges, but apart from that, we only - # look into a block when all the previous blocks have been done. - self._max_depth = 0 - for block in blocks: - depth = self._do_stack_depth_walk(block) - if block.auto_inserted_return and depth != 0: - os.write(2, "StackDepthComputationError in %s at %s:%s\n" % ( - self.compile_info.filename, self.name, self.first_lineno)) - raise StackDepthComputationError # fatal error - return self._max_depth - - def _next_stack_depth_walk(self, nextblock, depth): - if depth > nextblock.initial_depth: - nextblock.initial_depth = depth - - def _do_stack_depth_walk(self, block): - depth = block.initial_depth - for instr in block.instructions: - depth += _opcode_stack_effect(instr.opcode, instr.arg) - if depth >= self._max_depth: - self._max_depth = depth - jump_op = instr.opcode - if instr.has_jump: - target_depth = depth - if jump_op == ops.FOR_ITER: - target_depth -= 2 - elif (jump_op == ops.SETUP_FINALLY or - jump_op == ops.SETUP_EXCEPT or - jump_op == ops.SETUP_WITH): - if jump_op == ops.SETUP_FINALLY: - target_depth += 4 - elif jump_op == ops.SETUP_EXCEPT: - target_depth += 4 - elif jump_op == ops.SETUP_WITH: - target_depth += 3 - if target_depth > self._max_depth: - self._max_depth = target_depth - elif (jump_op == ops.JUMP_IF_TRUE_OR_POP or - jump_op == ops.JUMP_IF_FALSE_OR_POP): - depth -= 1 - self._next_stack_depth_walk(instr.jump[0], target_depth) - if jump_op == ops.JUMP_ABSOLUTE or jump_op == ops.JUMP_FORWARD: - # Nothing more can occur. - break - elif jump_op == ops.RETURN_VALUE or jump_op == ops.RAISE_VARARGS: - # Nothing more can occur. - break - else: - if block.next_block: - self._next_stack_depth_walk(block.next_block, depth) - return depth - - def _build_lnotab(self, blocks): - """Build the line number table for tracebacks and tracing.""" - current_line = self.first_lineno - current_off = 0 - table = [] - push = table.append - for block in blocks: - offset = block.offset - for instr in block.instructions: - if instr.lineno: - # compute deltas - line = instr.lineno - current_line - if line < 0: - continue - addr = offset - current_off - # Python assumes that lineno always increases with - # increasing bytecode address (lnotab is unsigned - # char). Depending on when SET_LINENO instructions - # are emitted this is not always true. Consider the - # code: - # a = (1, - # b) - # In the bytecode stream, the assignment to "a" - # occurs after the loading of "b". This works with - # the C Python compiler because it only generates a - # SET_LINENO instruction for the assignment. - if line or addr: - while addr > 255: - push(chr(255)) - push(chr(0)) - addr -= 255 - while line > 255: - push(chr(addr)) - push(chr(255)) - line -= 255 - addr = 0 - push(chr(addr)) - push(chr(line)) - current_line = instr.lineno - current_off = offset - offset += instr.size() - return ''.join(table) - - def assemble(self): - """Build a PyCode object.""" - # Unless it's interactive, every code object must end in a return. - if not self.current_block.have_return: - self.use_next_block() - if self.add_none_to_final_return: - self.load_const(self.space.w_None) - self.emit_op(ops.RETURN_VALUE) - self.current_block.auto_inserted_return = True - # Set the first lineno if it is not already explicitly set. - if self.first_lineno == -1: - if self.first_block.instructions: - self.first_lineno = self.first_block.instructions[0].lineno - else: - self.first_lineno = 1 - blocks = self.first_block.post_order() - self._resolve_block_targets(blocks) - lnotab = self._build_lnotab(blocks) - stack_depth = self._stacksize(blocks) - consts_w = self._build_consts_array() - names = _list_from_dict(self.names) - var_names = _list_from_dict(self.var_names) - cell_names = _list_from_dict(self.cell_vars) - free_names = _list_from_dict(self.free_vars, len(cell_names)) - flags = self._get_code_flags() - # (Only) inherit compilerflags in PyCF_MASK - flags |= (self.compile_info.flags & consts.PyCF_MASK) - bytecode = ''.join([block.get_code() for block in blocks]) - return PyCode(self.space, - self.argcount, - self.kwonlyargcount, - len(self.var_names), - stack_depth, - flags, - bytecode, - list(consts_w), - names, - var_names, - self.compile_info.filename, - self.name, - self.first_lineno, - lnotab, - free_names, - cell_names, - self.compile_info.hidden_applevel) - - -def _list_from_dict(d, offset=0): - result = [None] * len(d) - for obj, index in d.iteritems(): - result[index - offset] = obj - return result - - -_static_opcode_stack_effects = { - ops.NOP: 0, - - ops.POP_TOP: -1, - ops.ROT_TWO: 0, - ops.ROT_THREE: 0, - ops.DUP_TOP: 1, - ops.DUP_TOP_TWO: 2, - - ops.UNARY_POSITIVE: 0, - ops.UNARY_NEGATIVE: 0, - ops.UNARY_NOT: 0, - ops.UNARY_INVERT: 0, - - ops.LIST_APPEND: -1, - ops.SET_ADD: -1, - ops.MAP_ADD: -2, -<<<<<<< local -======= - # XXX - ops.STORE_MAP: -2, ->>>>>>> other - - ops.BINARY_POWER: -1, - ops.BINARY_MULTIPLY: -1, - ops.BINARY_MODULO: -1, - ops.BINARY_ADD: -1, - ops.BINARY_SUBTRACT: -1, - ops.BINARY_SUBSCR: -1, - ops.BINARY_FLOOR_DIVIDE: -1, - ops.BINARY_TRUE_DIVIDE: -1, - ops.BINARY_MATRIX_MULTIPLY: -1, - ops.BINARY_LSHIFT: -1, - ops.BINARY_RSHIFT: -1, - ops.BINARY_AND: -1, - ops.BINARY_OR: -1, - ops.BINARY_XOR: -1, - - ops.INPLACE_FLOOR_DIVIDE: -1, - ops.INPLACE_TRUE_DIVIDE: -1, - ops.INPLACE_ADD: -1, - ops.INPLACE_SUBTRACT: -1, - ops.INPLACE_MULTIPLY: -1, - ops.INPLACE_MODULO: -1, - ops.INPLACE_POWER: -1, - ops.INPLACE_MATRIX_MULTIPLY: -1, - ops.INPLACE_LSHIFT: -1, - ops.INPLACE_RSHIFT: -1, - ops.INPLACE_AND: -1, - ops.INPLACE_OR: -1, - ops.INPLACE_XOR: -1, - - ops.STORE_SUBSCR: -3, - ops.DELETE_SUBSCR: -2, - - ops.GET_ITER: 0, - ops.FOR_ITER: 1, - ops.BREAK_LOOP: 0, - ops.CONTINUE_LOOP: 0, - ops.SETUP_LOOP: 0, - - ops.PRINT_EXPR: -1, - -<<<<<<< local - ops.WITH_CLEANUP_START: -1, - ops.WITH_CLEANUP_FINISH: -1, # XXX Sometimes more -======= - # TODO - ops.WITH_CLEANUP: -1, ->>>>>>> other - ops.LOAD_BUILD_CLASS: 1, -<<<<<<< local -======= - # TODO - ops.STORE_LOCALS: -1, ->>>>>>> other - ops.POP_BLOCK: 0, - ops.POP_EXCEPT: -1, - ops.END_FINALLY: -4, # assume always 4: we pretend that SETUP_FINALLY - # pushes 4. In truth, it would only push 1 and - # the corresponding END_FINALLY only pops 1. - ops.SETUP_WITH: 1, - ops.SETUP_FINALLY: 0, - ops.SETUP_EXCEPT: 0, - - ops.RETURN_VALUE: -1, - ops.YIELD_VALUE: 0, - ops.YIELD_FROM: -1, - ops.COMPARE_OP: -1, - - # TODO - ops.LOOKUP_METHOD: 1, - - ops.LOAD_NAME: 1, - ops.STORE_NAME: -1, - ops.DELETE_NAME: 0, - - ops.LOAD_FAST: 1, - ops.STORE_FAST: -1, - ops.DELETE_FAST: 0, - - ops.LOAD_ATTR: 0, - ops.STORE_ATTR: -2, - ops.DELETE_ATTR: -1, - - ops.LOAD_GLOBAL: 1, - ops.STORE_GLOBAL: -1, - ops.DELETE_GLOBAL: 0, - ops.DELETE_DEREF: 0, - - ops.LOAD_CLOSURE: 1, - ops.LOAD_DEREF: 1, - ops.STORE_DEREF: -1, - ops.DELETE_DEREF: 0, - - ops.LOAD_CONST: 1, - - ops.IMPORT_STAR: -1, - ops.IMPORT_NAME: -1, - ops.IMPORT_FROM: 1, - - ops.JUMP_FORWARD: 0, - ops.JUMP_ABSOLUTE: 0, - ops.JUMP_IF_TRUE_OR_POP: 0, - ops.JUMP_IF_FALSE_OR_POP: 0, - ops.POP_JUMP_IF_TRUE: -1, - ops.POP_JUMP_IF_FALSE: -1, - # TODO - ops.JUMP_IF_NOT_DEBUG: 0, - - # TODO - ops.BUILD_LIST_FROM_ARG: 1, -} - - -def _compute_UNPACK_SEQUENCE(arg): - return arg - 1 - -def _compute_UNPACK_EX(arg): - return (arg & 0xFF) + (arg >> 8) - -def _compute_BUILD_TUPLE(arg): - return 1 - arg - -def _compute_BUILD_LIST(arg): - return 1 - arg - -def _compute_BUILD_SET(arg): - return 1 - arg - -def _compute_BUILD_MAP(arg): - return 1 - 2 * arg - -def _compute_BUILD_MAP_UNPACK(arg): - return 1 - arg - -def _compute_MAKE_CLOSURE(arg): - return -2 - _num_args(arg) - ((arg >> 16) & 0xFFFF) - -def _compute_MAKE_FUNCTION(arg): - return -1 - _num_args(arg) - ((arg >> 16) & 0xFFFF) - -def _compute_BUILD_SLICE(arg): - if arg == 3: - return -2 - else: - return -1 - -def _compute_RAISE_VARARGS(arg): - return -arg - -def _num_args(oparg): - return (oparg % 256) + 2 * ((oparg // 256) % 256) - -def _compute_CALL_FUNCTION(arg): - return -_num_args(arg) - -def _compute_CALL_FUNCTION_VAR(arg): - return -_num_args(arg) - 1 - -def _compute_CALL_FUNCTION_KW(arg): - return -_num_args(arg) - 1 - -def _compute_CALL_FUNCTION_VAR_KW(arg): - return -_num_args(arg) - 2 - -def _compute_CALL_METHOD(arg): - return -_num_args(arg) - 1 - - -_stack_effect_computers = {} -for name, func in globals().items(): - if name.startswith("_compute_"): - func._always_inline_ = True - _stack_effect_computers[getattr(ops, name[9:])] = func -for op, value in _static_opcode_stack_effects.iteritems(): - def func(arg, _value=value): - return _value - func._always_inline_ = True - _stack_effect_computers[op] = func -del name, func, op, value - - -def _opcode_stack_effect(op, arg): - """Return the stack effect of a opcode an its argument.""" - if we_are_translated(): - for possible_op in ops.unrolling_opcode_descs: - # EXTENDED_ARG should never get in here. - if possible_op.index == ops.EXTENDED_ARG: - continue - if op == possible_op.index: - return _stack_effect_computers[possible_op.index](arg) - else: - raise AssertionError("unknown opcode: %s" % (op,)) - else: - try: - return _static_opcode_stack_effects[op] - except KeyError: - try: - return _stack_effect_computers[op](arg) - except KeyError: - raise KeyError("Unknown stack effect for %s (%s)" % - (ops.opname[op], op)) diff --git a/pypy/interpreter/astcompiler/astbuilder.py b/pypy/interpreter/astcompiler/astbuilder.py --- a/pypy/interpreter/astcompiler/astbuilder.py +++ b/pypy/interpreter/astcompiler/astbuilder.py @@ -4,6 +4,7 @@ from pypy.interpreter.pyparser.pygram import syms, tokens from pypy.interpreter.pyparser.error import SyntaxError from pypy.interpreter.pyparser import parsestring +from rpython.rlib.objectmodel import always_inline def ast_from_node(space, node, compile_info): @@ -1169,6 +1170,7 @@ raise return self.space.call_function(self.space.w_float, w_num_str) + @always_inline def handle_dictelement(self, node, i): if node.get_child(i).type == tokens.DOUBLESTAR: key = None @@ -1178,7 +1180,7 @@ key = self.handle_expr(node.get_child(i)) value = self.handle_expr(node.get_child(i+2)) i += 3 - return [i,key,value] + return (i,key,value) def handle_atom(self, atom_node): first_child = atom_node.get_child(0) @@ -1374,10 +1376,7 @@ set_maker.get_column()) def handle_dictcomp(self, dict_maker): - dictelement = self.handle_dictelement(dict_maker, 0) - i = dictelement[0] - key = dictelement[1] - value = dictelement[2] + i, key, value = self.handle_dictelement(dict_maker, 0) comps = self.comprehension_helper(dict_maker.get_child(i)) return ast.DictComp(key, value, comps, dict_maker.get_lineno(), dict_maker.get_column()) @@ -1387,10 +1386,9 @@ values = [] i = 0 while i < node.num_children(): - dictelement = self.handle_dictelement(node, i) - i = dictelement[0] - keys.append(dictelement[1]) - values.append(dictelement[2]) + i, key, value = self.handle_dictelement(node, i) + keys.append(key) + values.append(value) i += 1 return ast.Dict(keys, values, node.get_lineno(), node.get_column()) diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py --- a/pypy/interpreter/astcompiler/codegen.py +++ b/pypy/interpreter/astcompiler/codegen.py @@ -441,8 +441,7 @@ # 4. load class name self.load_const(self.space.wrap(cls.name.decode('utf-8'))) # 5. generate the rest of the code for the call - self._make_call(2, - cls.bases, cls.keywords) + self._make_call(2, cls.bases, cls.keywords) # 6. apply decorators if cls.decorator_list: for i in range(len(cls.decorator_list)): @@ -1348,8 +1347,7 @@ if self._optimize_method_call(call): return call.func.walkabout(self) - self._make_call(0, - call.args, call.keywords) + self._make_call(0, call.args, call.keywords) def _call_has_no_star_args(self, call): if call.args is not None: diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py --- a/pypy/interpreter/pyopcode.py +++ b/pypy/interpreter/pyopcode.py @@ -1056,7 +1056,7 @@ w_value = self.popvalue() w_gen = self.peekvalue() if isinstance(w_gen, Coroutine): - if (w_gen.descr_gi_code(w_gen).co_flags & consts.CO_COROUTINE and + if (w_gen.descr_gi_code(space).co_flags & consts.CO_COROUTINE and not self.pycode.co_flags & (consts.CO_COROUTINE | consts.CO_ITERABLE_COROUTINE)): raise oefmt(self.space.w_TypeError, @@ -1479,27 +1479,29 @@ self.pushvalue(res) def BEFORE_ASYNC_WITH(self, oparg, next_instr): + space = self.space w_manager = self.peekvalue() - w_enter = self.space.lookup(w_manager, "__aenter__") - w_descr = self.space.lookup(w_manager, "__aexit__") + w_enter = space.lookup(w_manager, "__aenter__") + w_descr = space.lookup(w_manager, "__aexit__") if w_enter is None or w_descr is None: - raise oefmt(self.space.w_AttributeError, + raise oefmt(space.w_AttributeError, "'%T' object is not a context manager (no __aenter__/" "__aexit__ method)", w_manager) - w_exit = self.space.get(w_descr, w_manager) + w_exit = space.get(w_descr, w_manager) self.settopvalue(w_exit) - w_result = self.space.get_and_call_function(w_enter, w_manager) + w_result = space.get_and_call_function(w_enter, w_manager) self.pushvalue(w_result) def GET_AITER(self, oparg, next_instr): + space = self.space w_obj = self.peekvalue() - w_func = self.space.lookup(w_obj, "__aiter__") + w_func = space.lookup(w_obj, "__aiter__") if w_func is None: raise oefmt(space.w_AttributeError, "object %T does not have __aiter__ method", w_obj) w_iter = space.get_and_call_function(w_func, w_obj) - w_awaitable = w_iter._GetAwaitableIter(self.space) + w_awaitable = w_iter._GetAwaitableIter(space) if w_awaitable is None: raise oefmt(space.w_TypeError, "'async for' received an invalid object " @@ -1507,14 +1509,15 @@ self.settopvalue(w_awaitable) def GET_ANEXT(self, oparg, next_instr): + space = self.space w_aiter = self.peekvalue() - w_func = self.space.lookup(w_aiter, "__anext__") + w_func = space.lookup(w_aiter, "__anext__") if w_func is None: raise oefmt(space.w_AttributeError, "object %T does not have __anext__ method", w_aiter) w_next_iter = space.get_and_call_function(w_func, w_aiter) - w_awaitable = w_next_iter._GetAwaitableIter(self.space) + w_awaitable = w_next_iter._GetAwaitableIter(space) if w_awaitable is None: raise oefmt(space.w_TypeError, "'async for' received an invalid object " diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py --- a/pypy/module/zipimport/interp_zipimport.py +++ b/pypy/module/zipimport/interp_zipimport.py @@ -85,7 +85,7 @@ def iteratekeys(self, space): return space.iter(self.keys(space)) - def itervalues(self, space): + def iteratevalues(self, space): return space.iter(self.values(space)) def iteritems(self, space): @@ -112,7 +112,7 @@ keys = interp2app(W_ZipCache.keys), iterkeys = interp2app(W_ZipCache.iteratekeys), values = interp2app(W_ZipCache.values), - itervalues = interp2app(W_ZipCache.itervalues), + itervalues = interp2app(W_ZipCache.iteratevalues), clear = interp2app(W_ZipCache.clear), __delitem__ = interp2app(W_ZipCache.delitem), ) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit