Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
44307d5e
Commit
44307d5e
authored
Mar 29, 2014
by
Paul Sokolovsky
Browse files
vm: Implement "with" statement (SETUP_WITH and WITH_CLEANUP bytecodes).
parent
682f9e63
Changes
3
Hide whitespace changes
Inline
Side-by-side
py/compile.c
View file @
44307d5e
...
...
@@ -1798,6 +1798,7 @@ void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, m
EMIT_ARG
(
setup_with
,
l_end
);
EMIT
(
pop_top
);
}
compile_increase_except_level
(
comp
);
// compile additional pre-bits and the body
compile_with_stmt_helper
(
comp
,
n
-
1
,
nodes
+
1
,
body
);
// finish this with block
...
...
@@ -1805,6 +1806,7 @@ void compile_with_stmt_helper(compiler_t *comp, int n, mp_parse_node_t *nodes, m
EMIT_ARG
(
load_const_tok
,
MP_TOKEN_KW_NONE
);
EMIT_ARG
(
label_assign
,
l_end
);
EMIT
(
with_cleanup
);
compile_decrease_except_level
(
comp
);
EMIT
(
end_finally
);
}
}
...
...
py/qstrdefs.h
View file @
44307d5e
...
...
@@ -16,6 +16,8 @@ Q(__qualname__)
Q
(
__repl_print__
)
Q
(
__bool__
)
Q
(
__enter__
)
Q
(
__exit__
)
Q
(
__len__
)
Q
(
__iter__
)
Q
(
__getitem__
)
...
...
py/vm.c
View file @
44307d5e
...
...
@@ -378,6 +378,73 @@ dispatch_loop:
break;
*/
case
MP_BC_SETUP_WITH
:
{
obj1
=
TOP
();
SET_TOP
(
rt_load_attr
(
obj1
,
MP_QSTR___exit__
));
mp_obj_t
dest
[
2
];
rt_load_method
(
obj1
,
MP_QSTR___enter__
,
dest
);
obj2
=
rt_call_method_n_kw
(
0
,
0
,
dest
);
SETUP_BLOCK
();
PUSH
(
obj2
);
break
;
}
case
MP_BC_WITH_CLEANUP
:
{
static
const
mp_obj_t
no_exc
[]
=
{
mp_const_none
,
mp_const_none
,
mp_const_none
};
if
(
TOP
()
==
mp_const_none
)
{
sp
--
;
obj1
=
TOP
();
SET_TOP
(
mp_const_none
);
obj2
=
rt_call_function_n_kw
(
obj1
,
3
,
0
,
no_exc
);
}
else
if
(
MP_OBJ_IS_SMALL_INT
(
TOP
()))
{
mp_obj_t
cause
=
POP
();
switch
(
MP_OBJ_SMALL_INT_VALUE
(
cause
))
{
case
UNWIND_RETURN
:
{
mp_obj_t
retval
=
POP
();
obj2
=
rt_call_function_n_kw
(
TOP
(),
3
,
0
,
no_exc
);
SET_TOP
(
retval
);
PUSH
(
cause
);
break
;
}
case
UNWIND_JUMP
:
{
obj2
=
rt_call_function_n_kw
(
sp
[
-
2
],
3
,
0
,
no_exc
);
// Pop __exit__ boundmethod at sp[-2]
sp
[
-
2
]
=
sp
[
-
1
];
sp
[
-
1
]
=
sp
[
0
];
SET_TOP
(
cause
);
break
;
}
default:
assert
(
0
);
}
}
else
if
(
mp_obj_is_exception_type
(
TOP
()))
{
mp_obj_t
args
[
3
]
=
{
sp
[
0
],
sp
[
-
1
],
sp
[
-
2
]};
obj2
=
rt_call_function_n_kw
(
sp
[
-
3
],
3
,
0
,
args
);
// Pop __exit__ boundmethod at sp[-3]
// TODO: Once semantics is proven, optimize for case when obj2 == True
sp
[
-
3
]
=
sp
[
-
2
];
sp
[
-
2
]
=
sp
[
-
1
];
sp
[
-
1
]
=
sp
[
0
];
sp
--
;
if
(
rt_is_true
(
obj2
))
{
// This is what CPython does
//PUSH(MP_OBJ_NEW_SMALL_INT(UNWIND_SILENCED));
// But what we need to do is - pop exception from value stack...
sp
-=
3
;
// ... pop with exception handler, and signal END_FINALLY
// to just execute finally handler normally (signalled by None
// on value stack)
assert
(
exc_sp
>=
exc_stack
);
assert
(
exc_sp
->
opcode
==
MP_BC_SETUP_WITH
);
exc_sp
--
;
PUSH
(
mp_const_none
);
}
}
else
{
assert
(
0
);
}
break
;
}
case
MP_BC_UNWIND_JUMP
:
DECODE_SLABEL
;
PUSH
((
void
*
)(
ip
+
unum
));
// push destination ip for jump
...
...
@@ -387,7 +454,7 @@ unwind_jump:
while
(
unum
>
0
)
{
unum
-=
1
;
assert
(
exc_sp
>=
exc_stack
);
if
(
exc_sp
->
opcode
==
MP_BC_SETUP_FINALLY
)
{
if
(
exc_sp
->
opcode
==
MP_BC_SETUP_FINALLY
||
exc_sp
->
opcode
==
MP_BC_SETUP_WITH
)
{
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is
...
...
@@ -601,7 +668,7 @@ unwind_jump:
case
MP_BC_RETURN_VALUE
:
unwind_return:
while
(
exc_sp
>=
exc_stack
)
{
if
(
exc_sp
->
opcode
==
MP_BC_SETUP_FINALLY
)
{
if
(
exc_sp
->
opcode
==
MP_BC_SETUP_FINALLY
||
exc_sp
->
opcode
==
MP_BC_SETUP_WITH
)
{
// We're going to run "finally" code as a coroutine
// (not calling it recursively). Set up a sentinel
// on a stack so it can return back to us when it is
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment