def AUGASSIGN(self, node): # AugAssign is awkward: must set the context explicitly and visit twice, # once with AugLoad context, once with AugStore context node.target.ctx = _ast.AugLoad() self.handleNode(node.target, node) self.handleNode(node.value, node) node.target.ctx = _ast.AugStore() self.handleNode(node.target, node)
def make_assign(i, bytecode): op = bytecode[i][2] if op == STORE_SUBSCR: return Statement.make_subscript(i, bytecode) prev_op = bytecode[i - 1][2] if i > 0 else -1 if prev_op in INPLACE_OPCODES: in_cls = Statement.INPLACE_OPERATORS[prev_op] i -= 1 i, rhs = Statement.make_expr(i - 1, bytecode, context=_ast.AugStore()) i, lhs = Statement.make_expr(i - 1, bytecode, context=_ast.AugLoad()) return i, _ast.AugAssign(lhs, in_cls(), rhs) else: # We can either have multiple assignments: a = b = c = 1 # or unpacked sequences: a, b = 1, foo() # the compiler does some optimization so that: a, b = c, d # does not rely on UNPACK_SEQUENCE, but a ROT_TWO (or ROT_THREE & ROT_TWO for 3 elements). # This happens for 2 or 3 elements to unpack targets = [] value = None has_unpack, has_ROT_2_3, has_multiple = False, False, 0 num_unpack = -1 j = i while j >= 0: op = bytecode[j][2] if op == UNPACK_SEQUENCE: has_unpack = True num_unpack = bytecode[j][3] break elif op in (ROT_TWO, ROT_THREE): has_ROT_2_3 = True break if op == DUP_TOP: has_multiple += 1 j -= 1 if has_unpack: return Statement.make_assign_unpack(i, bytecode, unpack_num=num_unpack) elif has_ROT_2_3: return Statement.make_assign_opt_unpack(i, bytecode) elif has_multiple > 0: return Statement.make_assign_chained(i, bytecode) else: # A simple assignment i, store_expr = Statement.make_expr(i, bytecode) i, value_expr = Statement.make_expr(i - 1, bytecode) return i, _ast.Assign([store_expr], value_expr) return i, None