mirror of
https://github.com/python/cpython.git
synced 2024-11-23 18:04:37 +08:00
gh-98831: rewrite SEND, GET_YIELD_FROM_ITER, RETURN_GENERATOR in the instruction definition DSL (#101516)
This commit is contained in:
parent
a52cc9853f
commit
04e06e20ee
@ -663,14 +663,10 @@ dummy_func(
|
||||
PREDICT(LOAD_CONST);
|
||||
}
|
||||
|
||||
// error: SEND stack effect depends on jump flag
|
||||
inst(SEND) {
|
||||
inst(SEND, (receiver, v -- receiver if (!jump), retval)) {
|
||||
assert(frame != &entry_frame);
|
||||
assert(STACK_LEVEL() >= 2);
|
||||
PyObject *v = POP();
|
||||
PyObject *receiver = TOP();
|
||||
bool jump = false;
|
||||
PySendResult gen_status;
|
||||
PyObject *retval;
|
||||
if (tstate->c_tracefunc == NULL) {
|
||||
gen_status = PyIter_Send(receiver, v, &retval);
|
||||
} else {
|
||||
@ -695,21 +691,20 @@ dummy_func(
|
||||
gen_status = PYGEN_NEXT;
|
||||
}
|
||||
}
|
||||
Py_DECREF(v);
|
||||
if (gen_status == PYGEN_ERROR) {
|
||||
assert(retval == NULL);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
if (gen_status == PYGEN_RETURN) {
|
||||
assert(retval != NULL);
|
||||
Py_DECREF(receiver);
|
||||
SET_TOP(retval);
|
||||
JUMPBY(oparg);
|
||||
jump = true;
|
||||
}
|
||||
else {
|
||||
assert(gen_status == PYGEN_NEXT);
|
||||
assert(retval != NULL);
|
||||
PUSH(retval);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2043,31 +2038,30 @@ dummy_func(
|
||||
ERROR_IF(iter == NULL, error);
|
||||
}
|
||||
|
||||
// stack effect: ( -- )
|
||||
inst(GET_YIELD_FROM_ITER) {
|
||||
inst(GET_YIELD_FROM_ITER, (iterable -- iter)) {
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
PyObject *iterable = TOP();
|
||||
PyObject *iter;
|
||||
if (PyCoro_CheckExact(iterable)) {
|
||||
/* `iterable` is a coroutine */
|
||||
if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||
/* and it is used in a 'yield from' expression of a
|
||||
regular generator. */
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(NULL);
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
goto error;
|
||||
}
|
||||
iter = iterable;
|
||||
}
|
||||
else if (!PyGen_CheckExact(iterable)) {
|
||||
else if (PyGen_CheckExact(iterable)) {
|
||||
iter = iterable;
|
||||
}
|
||||
else {
|
||||
/* `iterable` is not a generator. */
|
||||
iter = PyObject_GetIter(iterable);
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(iter);
|
||||
if (iter == NULL)
|
||||
if (iter == NULL) {
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(iterable);
|
||||
}
|
||||
PREDICT(LOAD_CONST);
|
||||
}
|
||||
@ -3010,8 +3004,7 @@ dummy_func(
|
||||
PUSH((PyObject *)func);
|
||||
}
|
||||
|
||||
// stack effect: ( -- )
|
||||
inst(RETURN_GENERATOR) {
|
||||
inst(RETURN_GENERATOR, (--)) {
|
||||
assert(PyFunction_Check(frame->f_funcobj));
|
||||
PyFunctionObject *func = (PyFunctionObject *)frame->f_funcobj;
|
||||
PyGenObject *gen = (PyGenObject *)_Py_MakeCoro(func);
|
||||
|
37
Python/generated_cases.c.h
generated
37
Python/generated_cases.c.h
generated
@ -865,12 +865,12 @@
|
||||
}
|
||||
|
||||
TARGET(SEND) {
|
||||
assert(frame != &entry_frame);
|
||||
assert(STACK_LEVEL() >= 2);
|
||||
PyObject *v = POP();
|
||||
PyObject *receiver = TOP();
|
||||
PySendResult gen_status;
|
||||
PyObject *v = PEEK(1);
|
||||
PyObject *receiver = PEEK(2);
|
||||
PyObject *retval;
|
||||
assert(frame != &entry_frame);
|
||||
bool jump = false;
|
||||
PySendResult gen_status;
|
||||
if (tstate->c_tracefunc == NULL) {
|
||||
gen_status = PyIter_Send(receiver, v, &retval);
|
||||
} else {
|
||||
@ -895,22 +895,24 @@
|
||||
gen_status = PYGEN_NEXT;
|
||||
}
|
||||
}
|
||||
Py_DECREF(v);
|
||||
if (gen_status == PYGEN_ERROR) {
|
||||
assert(retval == NULL);
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(v);
|
||||
if (gen_status == PYGEN_RETURN) {
|
||||
assert(retval != NULL);
|
||||
Py_DECREF(receiver);
|
||||
SET_TOP(retval);
|
||||
JUMPBY(oparg);
|
||||
jump = true;
|
||||
}
|
||||
else {
|
||||
assert(gen_status == PYGEN_NEXT);
|
||||
assert(retval != NULL);
|
||||
PUSH(retval);
|
||||
}
|
||||
STACK_SHRINK(1);
|
||||
STACK_GROW(((!jump) ? 1 : 0));
|
||||
POKE(1, retval);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
@ -2584,30 +2586,33 @@
|
||||
}
|
||||
|
||||
TARGET(GET_YIELD_FROM_ITER) {
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
PyObject *iterable = TOP();
|
||||
PyObject *iterable = PEEK(1);
|
||||
PyObject *iter;
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
if (PyCoro_CheckExact(iterable)) {
|
||||
/* `iterable` is a coroutine */
|
||||
if (!(frame->f_code->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE))) {
|
||||
/* and it is used in a 'yield from' expression of a
|
||||
regular generator. */
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(NULL);
|
||||
_PyErr_SetString(tstate, PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"in a non-coroutine generator");
|
||||
goto error;
|
||||
}
|
||||
iter = iterable;
|
||||
}
|
||||
else if (!PyGen_CheckExact(iterable)) {
|
||||
else if (PyGen_CheckExact(iterable)) {
|
||||
iter = iterable;
|
||||
}
|
||||
else {
|
||||
/* `iterable` is not a generator. */
|
||||
iter = PyObject_GetIter(iterable);
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(iter);
|
||||
if (iter == NULL)
|
||||
if (iter == NULL) {
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(iterable);
|
||||
}
|
||||
POKE(1, iter);
|
||||
PREDICT(LOAD_CONST);
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -99,7 +99,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||
case GET_AWAITABLE:
|
||||
return 1;
|
||||
case SEND:
|
||||
return -1;
|
||||
return 2;
|
||||
case YIELD_VALUE:
|
||||
return 1;
|
||||
case POP_EXCEPT:
|
||||
@ -259,7 +259,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||
case GET_ITER:
|
||||
return 1;
|
||||
case GET_YIELD_FROM_ITER:
|
||||
return -1;
|
||||
return 1;
|
||||
case FOR_ITER:
|
||||
return -1;
|
||||
case FOR_ITER_LIST:
|
||||
@ -327,7 +327,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
|
||||
case MAKE_FUNCTION:
|
||||
return -1;
|
||||
case RETURN_GENERATOR:
|
||||
return -1;
|
||||
return 0;
|
||||
case BUILD_SLICE:
|
||||
return -1;
|
||||
case FORMAT_VALUE:
|
||||
@ -445,7 +445,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||
case GET_AWAITABLE:
|
||||
return 1;
|
||||
case SEND:
|
||||
return -1;
|
||||
return ((!jump) ? 1 : 0) + 1;
|
||||
case YIELD_VALUE:
|
||||
return 1;
|
||||
case POP_EXCEPT:
|
||||
@ -605,7 +605,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||
case GET_ITER:
|
||||
return 1;
|
||||
case GET_YIELD_FROM_ITER:
|
||||
return -1;
|
||||
return 1;
|
||||
case FOR_ITER:
|
||||
return -1;
|
||||
case FOR_ITER_LIST:
|
||||
@ -673,7 +673,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
|
||||
case MAKE_FUNCTION:
|
||||
return -1;
|
||||
case RETURN_GENERATOR:
|
||||
return -1;
|
||||
return 0;
|
||||
case BUILD_SLICE:
|
||||
return -1;
|
||||
case FORMAT_VALUE:
|
||||
|
Loading…
Reference in New Issue
Block a user