py/compile: Fix async-for/async-with to work with simpler exc on stack.

There is now just the exception instance on the stack when an exception is
raised, not the full (type, exc, traceback).
pull/2461/head
Damien George 2016-09-28 11:52:13 +10:00
rodzic 443cc0114d
commit b32c01b748
5 zmienionych plików z 33 dodań i 10 usunięć

Wyświetl plik

@ -1710,14 +1710,12 @@ STATIC void compile_async_for_stmt(compiler_t *comp, mp_parse_node_struct_t *pns
EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration); EMIT_LOAD_GLOBAL(MP_QSTR_StopAsyncIteration);
EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH); EMIT_ARG(binary_op, MP_BINARY_OP_EXCEPTION_MATCH);
EMIT_ARG(pop_jump_if, false, try_finally_label); EMIT_ARG(pop_jump_if, false, try_finally_label);
EMIT(pop_top); EMIT(pop_top); // pop exception instance
EMIT(pop_top);
EMIT(pop_top);
EMIT(pop_except); EMIT(pop_except);
EMIT_ARG(jump, while_else_label); EMIT_ARG(jump, while_else_label);
EMIT_ARG(label_assign, try_finally_label); EMIT_ARG(label_assign, try_finally_label);
EMIT_ARG(adjust_stack_size, 3); EMIT_ARG(adjust_stack_size, 1); // if we jump here, the exc is on the stack
compile_decrease_except_level(comp); compile_decrease_except_level(comp);
EMIT(end_finally); EMIT(end_finally);
EMIT(end_except_handler); EMIT(end_except_handler);
@ -1778,9 +1776,21 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
EMIT_ARG(label_assign, try_exception_label); // start of exception handler EMIT_ARG(label_assign, try_exception_label); // start of exception handler
EMIT(start_except_handler); EMIT(start_except_handler);
EMIT(rot_three);
// at this point the stack contains: ..., __aexit__, self, exc
EMIT(dup_top);
#if MICROPY_CPYTHON_COMPAT
EMIT_ARG(load_attr, MP_QSTR___class__); // get type(exc)
#else
compile_load_id(comp, MP_QSTR_type);
EMIT(rot_two); EMIT(rot_two);
EMIT_ARG(call_function, 1, 0, 0); // get type(exc)
#endif
EMIT(rot_two);
EMIT_ARG(load_const_tok, MP_TOKEN_KW_NONE); // dummy traceback value
// at this point the stack contains: ..., __aexit__, self, type(exc), exc, None
EMIT_ARG(call_method, 3, 0, 0); EMIT_ARG(call_method, 3, 0, 0);
compile_yield_from(comp); compile_yield_from(comp);
EMIT_ARG(pop_jump_if, true, no_reraise_label); EMIT_ARG(pop_jump_if, true, no_reraise_label);
EMIT_ARG(raise_varargs, 0); EMIT_ARG(raise_varargs, 0);
@ -1789,7 +1799,7 @@ STATIC void compile_async_with_stmt_helper(compiler_t *comp, int n, mp_parse_nod
EMIT(pop_except); EMIT(pop_except);
EMIT_ARG(jump, end_label); EMIT_ARG(jump, end_label);
EMIT_ARG(adjust_stack_size, 5); EMIT_ARG(adjust_stack_size, 3); // adjust for __aexit__, self, exc
compile_decrease_except_level(comp); compile_decrease_except_level(comp);
EMIT(end_finally); EMIT(end_finally);
EMIT(end_except_handler); EMIT(end_except_handler);

Wyświetl plik

@ -4,7 +4,7 @@ class AContext:
async def __aenter__(self): async def __aenter__(self):
print('enter') print('enter')
async def __aexit__(self, exc_type, exc, tb): async def __aexit__(self, exc_type, exc, tb):
print('exit') print('exit', exc_type, exc)
async def f(): async def f():
async with AContext(): async with AContext():
@ -15,3 +15,13 @@ try:
o.send(None) o.send(None)
except StopIteration: except StopIteration:
print('finished') print('finished')
async def g():
async with AContext():
raise ValueError('error')
o = g()
try:
o.send(None)
except ValueError:
print('ValueError')

Wyświetl plik

@ -1,4 +1,7 @@
enter enter
body body
exit exit None None
finished finished
enter
exit <class 'ValueError'> error
ValueError

Wyświetl plik

@ -20,7 +20,7 @@ class AContext:
print('enter') print('enter')
print('f returned:', await f(10)) print('f returned:', await f(10))
async def __aexit__(self, exc_type, exc, tb): async def __aexit__(self, exc_type, exc, tb):
print('exit') print('exit', exc_type, exc)
print('f returned:', await f(20)) print('f returned:', await f(20))
async def coro(): async def coro():

Wyświetl plik

@ -9,7 +9,7 @@ coro yielded: 31
coro yielded: 32 coro yielded: 32
body f returned: 33 body f returned: 33
body end body end
exit exit None None
f start: 20 f start: 20
coro yielded: 21 coro yielded: 21
coro yielded: 22 coro yielded: 22