Skip to content

Commit 46491ba

Browse files
committed
Initial proof-of-concept for yielding synchronous functions.
1 parent 43fdb70 commit 46491ba

5 files changed

Lines changed: 116 additions & 3 deletions

File tree

Include/internal/pycore_genobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,12 @@ PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **);
3232

3333
PyAPI_FUNC(PyObject *)_PyCoro_GetAwaitableIter(PyObject *o);
3434
PyAPI_FUNC(PyObject *)_PyAsyncGenValueWrapperNew(PyThreadState *state, PyObject *);
35+
PyAPI_FUNC(PyObject *)_PyAsyncGenYieldFrom_New(PyThreadState *state, PyObject *);
3536

3637
extern PyTypeObject _PyCoroWrapper_Type;
3738
extern PyTypeObject _PyAsyncGenWrappedValue_Type;
3839
extern PyTypeObject _PyAsyncGenAThrow_Type;
40+
extern PyTypeObject _PyAsyncGenYieldFrom_Type;
3941

4042
#ifdef __cplusplus
4143
}

Include/internal/pycore_intrinsics.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
#define INTRINSIC_TYPEVARTUPLE 9
1919
#define INTRINSIC_SUBSCRIPT_GENERIC 10
2020
#define INTRINSIC_TYPEALIAS 11
21+
#define INSTRINSIC_ASYNC_GEN_WRAP_YIELD_FROM 12
2122

22-
#define MAX_INTRINSIC_1 11
23+
#define MAX_INTRINSIC_1 12
2324

2425

2526
/* Binary Functions: */

Objects/genobject.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2605,3 +2605,111 @@ async_gen_athrow_new(PyAsyncGenObject *gen, PyObject *args)
26052605
_PyObject_GC_TRACK((PyObject*)o);
26062606
return (PyObject*)o;
26072607
}
2608+
2609+
typedef struct {
2610+
PyObject_HEAD
2611+
PyObject *agyf_iterator;
2612+
} _PyAsyncGenYieldFrom;
2613+
2614+
#define _PyAsyncGenYieldFrom_CAST(op) ((_PyAsyncGenYieldFrom *)op)
2615+
2616+
static int
2617+
async_gen_yield_from_traverse(PyObject *op, visitproc visit, void *arg)
2618+
{
2619+
assert(op != NULL);
2620+
_PyAsyncGenYieldFrom *self = _PyAsyncGenYieldFrom_CAST(op);
2621+
Py_VISIT(self->agyf_iterator);
2622+
return 0;
2623+
}
2624+
2625+
static int
2626+
async_gen_yield_from_clear(PyObject *op)
2627+
{
2628+
assert(op != NULL);
2629+
_PyAsyncGenYieldFrom *self = _PyAsyncGenYieldFrom_CAST(op);
2630+
Py_CLEAR(self->agyf_iterator);
2631+
return 0;
2632+
}
2633+
2634+
static void
2635+
async_gen_yield_from_dealloc(PyObject *op)
2636+
{
2637+
assert(op != NULL);
2638+
_PyAsyncGenYieldFrom *self = _PyAsyncGenYieldFrom_CAST(op);
2639+
_PyObject_GC_UNTRACK(op);
2640+
(void)async_gen_yield_from_clear(op);
2641+
PyObject_GC_Del(op);
2642+
}
2643+
2644+
static PyObject *
2645+
async_gen_yield_from_iternext(PyObject *op)
2646+
{
2647+
assert(op != NULL);
2648+
_PyAsyncGenYieldFrom *self = _PyAsyncGenYieldFrom_CAST(op);
2649+
PyObject *result = PyIter_Next(self->agyf_iterator);
2650+
if (result == NULL) {
2651+
return NULL;
2652+
}
2653+
2654+
PyObject *wrapped = _PyAsyncGenValueWrapperNew(_PyThreadState_GET(), result);
2655+
Py_DECREF(result);
2656+
return wrapped;
2657+
}
2658+
2659+
PyTypeObject _PyAsyncGenYieldFrom_Type = {
2660+
PyVarObject_HEAD_INIT(&PyType_Type, 0)
2661+
"async_generator_yield_from", /* tp_name */
2662+
sizeof(_PyAsyncGenYieldFrom), /* tp_basicsize */
2663+
0, /* tp_itemsize */
2664+
/* methods */
2665+
async_gen_yield_from_dealloc, /* tp_dealloc */
2666+
0, /* tp_vectorcall_offset */
2667+
0, /* tp_getattr */
2668+
0, /* tp_setattr */
2669+
0, /* tp_as_async */
2670+
0, /* tp_repr */
2671+
0, /* tp_as_number */
2672+
0, /* tp_as_sequence */
2673+
0, /* tp_as_mapping */
2674+
0, /* tp_hash */
2675+
0, /* tp_call */
2676+
0, /* tp_str */
2677+
PyObject_GenericGetAttr, /* tp_getattro */
2678+
0, /* tp_setattro */
2679+
0, /* tp_as_buffer */
2680+
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
2681+
0, /* tp_doc */
2682+
async_gen_yield_from_traverse, /* tp_traverse */
2683+
async_gen_yield_from_clear, /* tp_clear */
2684+
0, /* tp_richcompare */
2685+
0, /* tp_weaklistoffset */
2686+
PyObject_SelfIter, /* tp_iter */
2687+
async_gen_yield_from_iternext, /* tp_iternext */
2688+
0, /* tp_methods */
2689+
0, /* tp_members */
2690+
0, /* tp_getset */
2691+
0, /* tp_base */
2692+
0, /* tp_dict */
2693+
0, /* tp_descr_get */
2694+
0, /* tp_descr_set */
2695+
0, /* tp_dictoffset */
2696+
0, /* tp_init */
2697+
0, /* tp_alloc */
2698+
0, /* tp_new */
2699+
};
2700+
2701+
2702+
PyObject *
2703+
_PyAsyncGenYieldFrom_New(PyThreadState *tstate, PyObject *iterator)
2704+
{
2705+
assert(tstate != NULL);
2706+
assert(iterator != NULL);
2707+
_PyAsyncGenYieldFrom *yield_from = PyObject_GC_New(_PyAsyncGenYieldFrom,
2708+
&_PyAsyncGenYieldFrom_Type);
2709+
if (yield_from == NULL) {
2710+
return NULL;
2711+
}
2712+
yield_from->agyf_iterator = Py_NewRef(iterator);
2713+
_PyObject_GC_TRACK((PyObject *)yield_from);
2714+
return (PyObject *)yield_from;
2715+
}

Python/codegen.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5404,10 +5404,11 @@ codegen_visit_expr(compiler *c, expr_ty e)
54045404
if (!_PyST_IsFunctionLike(SYMTABLE_ENTRY(c))) {
54055405
return _PyCompile_Error(c, loc, "'yield from' outside function");
54065406
}
5407+
5408+
VISIT(c, expr, e->v.YieldFrom.value);
54075409
if (SCOPE_TYPE(c) == COMPILE_SCOPE_ASYNC_FUNCTION) {
5408-
return _PyCompile_Error(c, loc, "'yield from' inside async function");
5410+
ADDOP_I(c, loc, CALL_INTRINSIC_1, INSTRINSIC_ASYNC_GEN_WRAP_YIELD_FROM);
54095411
}
5410-
VISIT(c, expr, e->v.YieldFrom.value);
54115412
ADDOP(c, loc, GET_YIELD_FROM_ITER);
54125413
ADDOP_LOAD_CONST(c, loc, Py_None);
54135414
ADD_YIELD_FROM(c, loc, 0);

Python/intrinsics.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ _PyIntrinsics_UnaryFunctions[] = {
219219
INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEVARTUPLE, _Py_make_typevartuple)
220220
INTRINSIC_FUNC_ENTRY(INTRINSIC_SUBSCRIPT_GENERIC, _Py_subscript_generic)
221221
INTRINSIC_FUNC_ENTRY(INTRINSIC_TYPEALIAS, _Py_make_typealias)
222+
INTRINSIC_FUNC_ENTRY(INSTRINSIC_ASYNC_GEN_WRAP_YIELD_FROM, _PyAsyncGenYieldFrom_New)
222223
};
223224

224225

0 commit comments

Comments
 (0)