Skip to content

Commit cf21a4e

Browse files
committed
py: Core "yield from" implementation.
1 parent 182c31a commit cf21a4e

1 file changed

Lines changed: 56 additions & 1 deletion

File tree

py/vm.c

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "runtime.h"
1010
#include "bc0.h"
1111
#include "bc.h"
12+
#include "objgenerator.h"
1213

1314
// Value stack grows up (this makes it incompatible with native C stack, but
1415
// makes sure that arguments to functions are in natural order arg1..argN
@@ -138,7 +139,9 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
138139
// If we have exception to inject, now that we finish setting up
139140
// execution context, raise it. This works as if RAISE_VARARGS
140141
// bytecode was executed.
141-
if (inject_exc != MP_OBJ_NULL) {
142+
// Injecting exc into yield from generator is a special case,
143+
// handled by MP_BC_YIELD_FROM itself
144+
if (inject_exc != MP_OBJ_NULL && *ip != MP_BC_YIELD_FROM) {
142145
mp_obj_t t = inject_exc;
143146
inject_exc = MP_OBJ_NULL;
144147
nlr_jump(rt_make_raise_obj(t));
@@ -631,12 +634,64 @@ mp_vm_return_kind_t mp_execute_byte_code_2(const byte *code_info, const byte **i
631634
nlr_jump(rt_make_raise_obj(obj1));
632635

633636
case MP_BC_YIELD_VALUE:
637+
yield:
634638
nlr_pop();
635639
*ip_in_out = ip;
636640
*sp_in_out = sp;
637641
*exc_sp_in_out = MP_TAGPTR_MAKE(exc_sp, currently_in_except_block);
638642
return MP_VM_RETURN_YIELD;
639643

644+
case MP_BC_YIELD_FROM:
645+
{
646+
//#define EXC_MATCH(exc, type) MP_OBJ_IS_TYPE(exc, type)
647+
#define EXC_MATCH(exc, type) mp_obj_exception_match(exc, type)
648+
mp_vm_return_kind_t ret_kind;
649+
obj1 = POP();
650+
mp_obj_t t = MP_OBJ_NULL;
651+
if (inject_exc != MP_OBJ_NULL) {
652+
t = inject_exc;
653+
inject_exc = MP_OBJ_NULL;
654+
obj2 = mp_obj_gen_resume(TOP(), mp_const_none, t, &ret_kind);
655+
} else {
656+
obj2 = mp_obj_gen_resume(TOP(), obj1, MP_OBJ_NULL, &ret_kind);
657+
}
658+
659+
if (ret_kind == MP_VM_RETURN_YIELD) {
660+
ip--;
661+
PUSH(obj2);
662+
goto yield;
663+
}
664+
if (ret_kind == MP_VM_RETURN_NORMAL) {
665+
// Pop exhausted gen
666+
sp--;
667+
if (obj2 == MP_OBJ_NULL) {
668+
// Optimize StopIteration
669+
// TODO: get StopIteration's value
670+
PUSH(mp_const_none);
671+
} else {
672+
PUSH(obj2);
673+
}
674+
675+
// if it swallowed it, we re-raise GeneratorExit
676+
if (t != MP_OBJ_NULL && EXC_MATCH(t, &mp_type_GeneratorExit)) {
677+
nlr_jump(t);
678+
}
679+
680+
break;
681+
}
682+
if (ret_kind == MP_VM_RETURN_EXCEPTION) {
683+
// Pop exhausted gen
684+
sp--;
685+
if (EXC_MATCH(obj2, &mp_type_StopIteration)) {
686+
printf("Generator explicitly raised StopIteration\n");
687+
PUSH(mp_const_none);
688+
break;
689+
} else {
690+
nlr_jump(obj2);
691+
}
692+
}
693+
}
694+
640695
case MP_BC_IMPORT_NAME:
641696
DECODE_QSTR;
642697
obj1 = POP();

0 commit comments

Comments
 (0)