Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Include/internal/pycore_ceval.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ PyAPI_FUNC(PyObject **) _PyObjectArray_FromStackRefArray(_PyStackRef *input, Py_

PyAPI_FUNC(void) _PyObjectArray_Free(PyObject **array, PyObject **scratch);

PyAPI_FUNC(PyObject *) _PyEval_GetANext(PyObject *aiter);
PyAPI_FUNC(PyObject *) _PyEval_LoadGlobal(PyObject *globals, PyObject *builtins, PyObject *name);
PyAPI_FUNC(PyObject *) _PyEval_GetAwaitable(PyObject *iterable, int oparg);
PyAPI_FUNC(PyObject *) _PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name);

/* Bits that can be set in PyThreadState.eval_breaker */
#define _PY_GIL_DROP_REQUEST_BIT (1U << 0)
Expand Down
125 changes: 8 additions & 117 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1010,77 +1010,16 @@ dummy_func(
}

inst(GET_ANEXT, (aiter -- aiter, awaitable)) {
unaryfunc getter = NULL;
PyObject *next_iter = NULL;
PyObject *awaitable_o;
PyObject *aiter_o = PyStackRef_AsPyObjectBorrow(aiter);
PyTypeObject *type = Py_TYPE(aiter_o);

if (PyAsyncGen_CheckExact(aiter_o)) {
awaitable_o = type->tp_as_async->am_anext(aiter_o);
if (awaitable_o == NULL) {
ERROR_NO_POP();
}
} else {
if (type->tp_as_async != NULL){
getter = type->tp_as_async->am_anext;
}

if (getter != NULL) {
next_iter = (*getter)(aiter_o);
if (next_iter == NULL) {
ERROR_NO_POP();
}
}
else {
_PyErr_Format(tstate, PyExc_TypeError,
"'async for' requires an iterator with "
"__anext__ method, got %.100s",
type->tp_name);
ERROR_NO_POP();
}

awaitable_o = _PyCoro_GetAwaitableIter(next_iter);
if (awaitable_o == NULL) {
_PyErr_FormatFromCause(
PyExc_TypeError,
"'async for' received an invalid object "
"from __anext__: %.100s",
Py_TYPE(next_iter)->tp_name);

Py_DECREF(next_iter);
ERROR_NO_POP();
} else {
Py_DECREF(next_iter);
}
PyObject *awaitable_o = _PyEval_GetANext(PyStackRef_AsPyObjectBorrow(aiter));
if (awaitable_o == NULL) {
ERROR_NO_POP();
}
awaitable = PyStackRef_FromPyObjectSteal(awaitable_o);
}

inst(GET_AWAITABLE, (iterable -- iter)) {
PyObject *iter_o = _PyCoro_GetAwaitableIter(PyStackRef_AsPyObjectBorrow(iterable));

if (iter_o == NULL) {
_PyEval_FormatAwaitableError(tstate,
Py_TYPE(PyStackRef_AsPyObjectBorrow(iterable)), oparg);
}

PyObject *iter_o = _PyEval_GetAwaitable(PyStackRef_AsPyObjectBorrow(iterable), oparg);
DECREF_INPUTS();

if (iter_o != NULL && PyCoro_CheckExact(iter_o)) {
PyObject *yf = _PyGen_yf((PyGenObject*)iter_o);
if (yf != NULL) {
/* `iter` is a coroutine object that is being
awaited, `yf` is a pointer to the current awaitable
being awaited on. */
Py_DECREF(yf);
Py_CLEAR(iter_o);
_PyErr_SetString(tstate, PyExc_RuntimeError,
"coroutine is being awaited already");
/* The code below jumps to `error` if `iter` is NULL. */
}
}

ERROR_IF(iter_o == NULL, error);
iter = PyStackRef_FromPyObjectSteal(iter_o);
}
Expand Down Expand Up @@ -1527,27 +1466,9 @@ dummy_func(
}

inst(LOAD_NAME, (-- v)) {
PyObject *v_o;
PyObject *mod_or_class_dict = LOCALS();
if (mod_or_class_dict == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
"no locals found");
ERROR_IF(true, error);
}
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg);
ERROR_IF(PyMapping_GetOptionalItem(mod_or_class_dict, name, &v_o) < 0, error);
if (v_o == NULL) {
ERROR_IF(PyDict_GetItemRef(GLOBALS(), name, &v_o) < 0, error);
if (v_o == NULL) {
ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &v_o) < 0, error);
if (v_o == NULL) {
_PyEval_FormatExcCheckArg(
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
ERROR_IF(true, error);
}
}
}
PyObject *v_o = _PyEval_LoadName(tstate, frame, name);
ERROR_IF(v_o == NULL, error);
v = PyStackRef_FromPyObjectSteal(v_o);
}

Expand All @@ -1571,38 +1492,8 @@ dummy_func(

op(_LOAD_GLOBAL, ( -- res, null if (oparg & 1))) {
PyObject *name = GETITEM(FRAME_CO_NAMES, oparg>>1);
PyObject *res_o;
if (PyDict_CheckExact(GLOBALS())
&& PyDict_CheckExact(BUILTINS()))
{
res_o = _PyDict_LoadGlobal((PyDictObject *)GLOBALS(),
(PyDictObject *)BUILTINS(),
name);
if (res_o == NULL) {
if (!_PyErr_Occurred(tstate)) {
/* _PyDict_LoadGlobal() returns NULL without raising
* an exception if the key doesn't exist */
_PyEval_FormatExcCheckArg(tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
ERROR_IF(true, error);
}
}
else {
/* Slow-path if globals or builtins is not a dict */
/* namespace 1: globals */
ERROR_IF(PyMapping_GetOptionalItem(GLOBALS(), name, &res_o) < 0, error);
if (res_o == NULL) {
/* namespace 2: builtins */
ERROR_IF(PyMapping_GetOptionalItem(BUILTINS(), name, &res_o) < 0, error);
if (res_o == NULL) {
_PyEval_FormatExcCheckArg(
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
ERROR_IF(true, error);
}
}
}
PyObject *res_o = _PyEval_LoadGlobal(GLOBALS(), BUILTINS(), name);
ERROR_IF(res_o == NULL, error);
null = PyStackRef_NULL;
res = PyStackRef_FromPyObjectSteal(res_o);
}
Expand Down
135 changes: 135 additions & 0 deletions Python/ceval.c
Original file line number Diff line number Diff line change
Expand Up @@ -720,6 +720,7 @@ _PyObjectArray_Free(PyObject **array, PyObject **scratch)
}
}


/* _PyEval_EvalFrameDefault() is a *big* function,
* so consume 3 units of C stack */
#define PY_EVAL_C_STACK_UNITS 2
Expand Down Expand Up @@ -3031,3 +3032,137 @@ void Py_LeaveRecursiveCall(void)
{
_Py_LeaveRecursiveCall();
}

PyObject *
_PyEval_GetANext(PyObject *aiter)
{
unaryfunc getter = NULL;
PyObject *next_iter = NULL;
PyTypeObject *type = Py_TYPE(aiter);
if (PyAsyncGen_CheckExact(aiter)) {
return type->tp_as_async->am_anext(aiter);
}
if (type->tp_as_async != NULL){
getter = type->tp_as_async->am_anext;
}

if (getter != NULL) {
next_iter = (*getter)(aiter);
if (next_iter == NULL) {
return NULL;
}
}
else {
PyErr_Format(PyExc_TypeError,
"'async for' requires an iterator with "
"__anext__ method, got %.100s",
type->tp_name);
return NULL;
}

PyObject *awaitable = _PyCoro_GetAwaitableIter(next_iter);
if (awaitable == NULL) {
_PyErr_FormatFromCause(
PyExc_TypeError,
"'async for' received an invalid object "
"from __anext__: %.100s",
Py_TYPE(next_iter)->tp_name);
}
Py_DECREF(next_iter);
return awaitable;
}

PyObject *
_PyEval_LoadGlobal(PyObject *globals, PyObject *builtins, PyObject *name)
{
PyObject *res;
if (PyDict_CheckExact(globals) && PyDict_CheckExact(builtins)) {
res = _PyDict_LoadGlobal((PyDictObject *)globals,
(PyDictObject *)builtins,
name);
if (res == NULL && !PyErr_Occurred()) {
/* _PyDict_LoadGlobal() returns NULL without raising
* an exception if the key doesn't exist */
_PyEval_FormatExcCheckArg(PyThreadState_GET(), PyExc_NameError,
NAME_ERROR_MSG, name);
}
}
else {
/* Slow-path if globals or builtins is not a dict */
/* namespace 1: globals */
if (PyMapping_GetOptionalItem(globals, name, &res) < 0) {
return NULL;
}
if (res == NULL) {
/* namespace 2: builtins */
if (PyMapping_GetOptionalItem(builtins, name, &res) < 0) {
return NULL;
}
if (res == NULL) {
_PyEval_FormatExcCheckArg(
PyThreadState_GET(), PyExc_NameError,
NAME_ERROR_MSG, name);
}
}
}
return res;
}

PyObject *
_PyEval_GetAwaitable(PyObject *iterable, int oparg)
{
PyObject *iter = _PyCoro_GetAwaitableIter(iterable);

if (iter == NULL) {
_PyEval_FormatAwaitableError(PyThreadState_GET(),
Py_TYPE(iterable), oparg);
}
else if (PyCoro_CheckExact(iter)) {
PyObject *yf = _PyGen_yf((PyGenObject*)iter);
if (yf != NULL) {
/* `iter` is a coroutine object that is being
awaited, `yf` is a pointer to the current awaitable
being awaited on. */
Py_DECREF(yf);
Py_CLEAR(iter);
_PyErr_SetString(PyThreadState_GET(), PyExc_RuntimeError,
"coroutine is being awaited already");
}
}
return iter;
}

PyObject *
_PyEval_LoadName(PyThreadState *tstate, _PyInterpreterFrame *frame, PyObject *name)
{

PyObject *value;
if (frame->f_locals == NULL) {
_PyErr_SetString(tstate, PyExc_SystemError,
"no locals found");
return NULL;
}
if (PyMapping_GetOptionalItem(frame->f_locals, name, &value) < 0) {
return NULL;
}
if (value != NULL) {
return value;
}
if (PyDict_GetItemRef(frame->f_globals, name, &value) < 0) {
return NULL;
}
if (value != NULL) {
return value;
}
if (PyMapping_GetOptionalItem(frame->f_builtins, name, &value) < 0) {
return NULL;
}
if (value == NULL) {
_PyEval_FormatExcCheckArg(
tstate, PyExc_NameError,
NAME_ERROR_MSG, name);
}
return value;
}


Loading