mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
PEP 0492 -- Coroutines with async and await syntax. Issue #24017.
This commit is contained in:
parent
4e6bf4b3da
commit
7544508f02
72 changed files with 9261 additions and 5739 deletions
|
@ -45,6 +45,14 @@ static char *FunctionDef_fields[]={
|
|||
"decorator_list",
|
||||
"returns",
|
||||
};
|
||||
static PyTypeObject *AsyncFunctionDef_type;
|
||||
static char *AsyncFunctionDef_fields[]={
|
||||
"name",
|
||||
"args",
|
||||
"body",
|
||||
"decorator_list",
|
||||
"returns",
|
||||
};
|
||||
static PyTypeObject *ClassDef_type;
|
||||
_Py_IDENTIFIER(bases);
|
||||
_Py_IDENTIFIER(keywords);
|
||||
|
@ -87,6 +95,13 @@ static char *For_fields[]={
|
|||
"body",
|
||||
"orelse",
|
||||
};
|
||||
static PyTypeObject *AsyncFor_type;
|
||||
static char *AsyncFor_fields[]={
|
||||
"target",
|
||||
"iter",
|
||||
"body",
|
||||
"orelse",
|
||||
};
|
||||
static PyTypeObject *While_type;
|
||||
_Py_IDENTIFIER(test);
|
||||
static char *While_fields[]={
|
||||
|
@ -106,6 +121,11 @@ static char *With_fields[]={
|
|||
"items",
|
||||
"body",
|
||||
};
|
||||
static PyTypeObject *AsyncWith_type;
|
||||
static char *AsyncWith_fields[]={
|
||||
"items",
|
||||
"body",
|
||||
};
|
||||
static PyTypeObject *Raise_type;
|
||||
_Py_IDENTIFIER(exc);
|
||||
_Py_IDENTIFIER(cause);
|
||||
|
@ -228,6 +248,10 @@ static char *GeneratorExp_fields[]={
|
|||
"elt",
|
||||
"generators",
|
||||
};
|
||||
static PyTypeObject *Await_type;
|
||||
static char *Await_fields[]={
|
||||
"value",
|
||||
};
|
||||
static PyTypeObject *Yield_type;
|
||||
static char *Yield_fields[]={
|
||||
"value",
|
||||
|
@ -806,6 +830,9 @@ static int init_types(void)
|
|||
FunctionDef_type = make_type("FunctionDef", stmt_type, FunctionDef_fields,
|
||||
5);
|
||||
if (!FunctionDef_type) return 0;
|
||||
AsyncFunctionDef_type = make_type("AsyncFunctionDef", stmt_type,
|
||||
AsyncFunctionDef_fields, 5);
|
||||
if (!AsyncFunctionDef_type) return 0;
|
||||
ClassDef_type = make_type("ClassDef", stmt_type, ClassDef_fields, 5);
|
||||
if (!ClassDef_type) return 0;
|
||||
Return_type = make_type("Return", stmt_type, Return_fields, 1);
|
||||
|
@ -818,12 +845,16 @@ static int init_types(void)
|
|||
if (!AugAssign_type) return 0;
|
||||
For_type = make_type("For", stmt_type, For_fields, 4);
|
||||
if (!For_type) return 0;
|
||||
AsyncFor_type = make_type("AsyncFor", stmt_type, AsyncFor_fields, 4);
|
||||
if (!AsyncFor_type) return 0;
|
||||
While_type = make_type("While", stmt_type, While_fields, 3);
|
||||
if (!While_type) return 0;
|
||||
If_type = make_type("If", stmt_type, If_fields, 3);
|
||||
if (!If_type) return 0;
|
||||
With_type = make_type("With", stmt_type, With_fields, 2);
|
||||
if (!With_type) return 0;
|
||||
AsyncWith_type = make_type("AsyncWith", stmt_type, AsyncWith_fields, 2);
|
||||
if (!AsyncWith_type) return 0;
|
||||
Raise_type = make_type("Raise", stmt_type, Raise_fields, 2);
|
||||
if (!Raise_type) return 0;
|
||||
Try_type = make_type("Try", stmt_type, Try_fields, 4);
|
||||
|
@ -872,6 +903,8 @@ static int init_types(void)
|
|||
GeneratorExp_type = make_type("GeneratorExp", expr_type,
|
||||
GeneratorExp_fields, 2);
|
||||
if (!GeneratorExp_type) return 0;
|
||||
Await_type = make_type("Await", expr_type, Await_fields, 1);
|
||||
if (!Await_type) return 0;
|
||||
Yield_type = make_type("Yield", expr_type, Yield_fields, 1);
|
||||
if (!Yield_type) return 0;
|
||||
YieldFrom_type = make_type("YieldFrom", expr_type, YieldFrom_fields, 1);
|
||||
|
@ -1200,6 +1233,36 @@ FunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq *
|
|||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
AsyncFunctionDef(identifier name, arguments_ty args, asdl_seq * body, asdl_seq
|
||||
* decorator_list, expr_ty returns, int lineno, int col_offset,
|
||||
PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!name) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field name is required for AsyncFunctionDef");
|
||||
return NULL;
|
||||
}
|
||||
if (!args) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field args is required for AsyncFunctionDef");
|
||||
return NULL;
|
||||
}
|
||||
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->kind = AsyncFunctionDef_kind;
|
||||
p->v.AsyncFunctionDef.name = name;
|
||||
p->v.AsyncFunctionDef.args = args;
|
||||
p->v.AsyncFunctionDef.body = body;
|
||||
p->v.AsyncFunctionDef.decorator_list = decorator_list;
|
||||
p->v.AsyncFunctionDef.returns = returns;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
ClassDef(identifier name, asdl_seq * bases, asdl_seq * keywords, asdl_seq *
|
||||
body, asdl_seq * decorator_list, int lineno, int col_offset, PyArena
|
||||
|
@ -1334,6 +1397,34 @@ For(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
|
|||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
AsyncFor(expr_ty target, expr_ty iter, asdl_seq * body, asdl_seq * orelse, int
|
||||
lineno, int col_offset, PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
if (!target) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field target is required for AsyncFor");
|
||||
return NULL;
|
||||
}
|
||||
if (!iter) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field iter is required for AsyncFor");
|
||||
return NULL;
|
||||
}
|
||||
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->kind = AsyncFor_kind;
|
||||
p->v.AsyncFor.target = target;
|
||||
p->v.AsyncFor.iter = iter;
|
||||
p->v.AsyncFor.body = body;
|
||||
p->v.AsyncFor.orelse = orelse;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
While(expr_ty test, asdl_seq * body, asdl_seq * orelse, int lineno, int
|
||||
col_offset, PyArena *arena)
|
||||
|
@ -1394,6 +1485,22 @@ With(asdl_seq * items, asdl_seq * body, int lineno, int col_offset, PyArena
|
|||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
AsyncWith(asdl_seq * items, asdl_seq * body, int lineno, int col_offset,
|
||||
PyArena *arena)
|
||||
{
|
||||
stmt_ty p;
|
||||
p = (stmt_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->kind = AsyncWith_kind;
|
||||
p->v.AsyncWith.items = items;
|
||||
p->v.AsyncWith.body = body;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
}
|
||||
|
||||
stmt_ty
|
||||
Raise(expr_ty exc, expr_ty cause, int lineno, int col_offset, PyArena *arena)
|
||||
{
|
||||
|
@ -1821,6 +1928,25 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
|
|||
return p;
|
||||
}
|
||||
|
||||
expr_ty
|
||||
Await(expr_ty value, int lineno, int col_offset, PyArena *arena)
|
||||
{
|
||||
expr_ty p;
|
||||
if (!value) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"field value is required for Await");
|
||||
return NULL;
|
||||
}
|
||||
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
|
||||
if (!p)
|
||||
return NULL;
|
||||
p->kind = Await_kind;
|
||||
p->v.Await.value = value;
|
||||
p->lineno = lineno;
|
||||
p->col_offset = col_offset;
|
||||
return p;
|
||||
}
|
||||
|
||||
expr_ty
|
||||
Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
|
||||
{
|
||||
|
@ -2409,6 +2535,36 @@ ast2obj_stmt(void* _o)
|
|||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
result = PyType_GenericNew(AsyncFunctionDef_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_identifier(o->v.AsyncFunctionDef.name);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_name, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_arguments(o->v.AsyncFunctionDef.args);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_args, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->v.AsyncFunctionDef.body, ast2obj_stmt);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->v.AsyncFunctionDef.decorator_list,
|
||||
ast2obj_expr);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_decorator_list, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->v.AsyncFunctionDef.returns);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_returns, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case ClassDef_kind:
|
||||
result = PyType_GenericNew(ClassDef_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
|
@ -2513,6 +2669,30 @@ ast2obj_stmt(void* _o)
|
|||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case AsyncFor_kind:
|
||||
result = PyType_GenericNew(AsyncFor_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_expr(o->v.AsyncFor.target);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_target, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_expr(o->v.AsyncFor.iter);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_iter, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->v.AsyncFor.body, ast2obj_stmt);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->v.AsyncFor.orelse, ast2obj_stmt);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_orelse, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case While_kind:
|
||||
result = PyType_GenericNew(While_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
|
@ -2565,6 +2745,20 @@ ast2obj_stmt(void* _o)
|
|||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case AsyncWith_kind:
|
||||
result = PyType_GenericNew(AsyncWith_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_list(o->v.AsyncWith.items, ast2obj_withitem);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_items, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
value = ast2obj_list(o->v.AsyncWith.body, ast2obj_stmt);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_body, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Raise_kind:
|
||||
result = PyType_GenericNew(Raise_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
|
@ -2878,6 +3072,15 @@ ast2obj_expr(void* _o)
|
|||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Await_kind:
|
||||
result = PyType_GenericNew(Await_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
value = ast2obj_expr(o->v.Await.value);
|
||||
if (!value) goto failed;
|
||||
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
|
||||
goto failed;
|
||||
Py_DECREF(value);
|
||||
break;
|
||||
case Yield_kind:
|
||||
result = PyType_GenericNew(Yield_type, NULL, NULL);
|
||||
if (!result) goto failed;
|
||||
|
@ -3832,6 +4035,102 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFunctionDef_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
}
|
||||
if (isinstance) {
|
||||
identifier name;
|
||||
arguments_ty args;
|
||||
asdl_seq* body;
|
||||
asdl_seq* decorator_list;
|
||||
expr_ty returns;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_name)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_name);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_identifier(tmp, &name, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"name\" missing from AsyncFunctionDef");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_args)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_args);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_arguments(tmp, &args, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"args\" missing from AsyncFunctionDef");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_body)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_body);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
body = _Py_asdl_seq_new(len, arena);
|
||||
if (body == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
stmt_ty value;
|
||||
res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(body, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFunctionDef");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_decorator_list)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_decorator_list);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncFunctionDef field \"decorator_list\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
decorator_list = _Py_asdl_seq_new(len, arena);
|
||||
if (decorator_list == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
expr_ty value;
|
||||
res = obj2ast_expr(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(decorator_list, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"decorator_list\" missing from AsyncFunctionDef");
|
||||
return 1;
|
||||
}
|
||||
if (exists_not_none(obj, &PyId_returns)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_returns);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_expr(tmp, &returns, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
returns = NULL;
|
||||
}
|
||||
*out = AsyncFunctionDef(name, args, body, decorator_list, returns,
|
||||
lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)ClassDef_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
|
@ -4188,6 +4487,90 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncFor_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
}
|
||||
if (isinstance) {
|
||||
expr_ty target;
|
||||
expr_ty iter;
|
||||
asdl_seq* body;
|
||||
asdl_seq* orelse;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_target)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_target);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_expr(tmp, &target, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"target\" missing from AsyncFor");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_iter)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_iter);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_expr(tmp, &iter, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"iter\" missing from AsyncFor");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_body)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_body);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncFor field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
body = _Py_asdl_seq_new(len, arena);
|
||||
if (body == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
stmt_ty value;
|
||||
res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(body, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncFor");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_orelse)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_orelse);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncFor field \"orelse\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
orelse = _Py_asdl_seq_new(len, arena);
|
||||
if (orelse == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
stmt_ty value;
|
||||
res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(orelse, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"orelse\" missing from AsyncFor");
|
||||
return 1;
|
||||
}
|
||||
*out = AsyncFor(target, iter, body, orelse, lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)While_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
|
@ -4392,6 +4775,66 @@ obj2ast_stmt(PyObject* obj, stmt_ty* out, PyArena* arena)
|
|||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)AsyncWith_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
}
|
||||
if (isinstance) {
|
||||
asdl_seq* items;
|
||||
asdl_seq* body;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_items)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_items);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncWith field \"items\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
items = _Py_asdl_seq_new(len, arena);
|
||||
if (items == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
withitem_ty value;
|
||||
res = obj2ast_withitem(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(items, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"items\" missing from AsyncWith");
|
||||
return 1;
|
||||
}
|
||||
if (_PyObject_HasAttrId(obj, &PyId_body)) {
|
||||
int res;
|
||||
Py_ssize_t len;
|
||||
Py_ssize_t i;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_body);
|
||||
if (tmp == NULL) goto failed;
|
||||
if (!PyList_Check(tmp)) {
|
||||
PyErr_Format(PyExc_TypeError, "AsyncWith field \"body\" must be a list, not a %.200s", tmp->ob_type->tp_name);
|
||||
goto failed;
|
||||
}
|
||||
len = PyList_GET_SIZE(tmp);
|
||||
body = _Py_asdl_seq_new(len, arena);
|
||||
if (body == NULL) goto failed;
|
||||
for (i = 0; i < len; i++) {
|
||||
stmt_ty value;
|
||||
res = obj2ast_stmt(PyList_GET_ITEM(tmp, i), &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
asdl_seq_SET(body, i, value);
|
||||
}
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"body\" missing from AsyncWith");
|
||||
return 1;
|
||||
}
|
||||
*out = AsyncWith(items, body, lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)Raise_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
|
@ -5326,6 +5769,28 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
|
|||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)Await_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
}
|
||||
if (isinstance) {
|
||||
expr_ty value;
|
||||
|
||||
if (_PyObject_HasAttrId(obj, &PyId_value)) {
|
||||
int res;
|
||||
tmp = _PyObject_GetAttrId(obj, &PyId_value);
|
||||
if (tmp == NULL) goto failed;
|
||||
res = obj2ast_expr(tmp, &value, arena);
|
||||
if (res != 0) goto failed;
|
||||
Py_CLEAR(tmp);
|
||||
} else {
|
||||
PyErr_SetString(PyExc_TypeError, "required field \"value\" missing from Await");
|
||||
return 1;
|
||||
}
|
||||
*out = Await(value, lineno, col_offset, arena);
|
||||
if (*out == NULL) goto failed;
|
||||
return 0;
|
||||
}
|
||||
isinstance = PyObject_IsInstance(obj, (PyObject*)Yield_type);
|
||||
if (isinstance == -1) {
|
||||
return 1;
|
||||
|
@ -6782,6 +7247,8 @@ PyInit__ast(void)
|
|||
if (PyDict_SetItemString(d, "stmt", (PyObject*)stmt_type) < 0) return NULL;
|
||||
if (PyDict_SetItemString(d, "FunctionDef", (PyObject*)FunctionDef_type) <
|
||||
0) return NULL;
|
||||
if (PyDict_SetItemString(d, "AsyncFunctionDef",
|
||||
(PyObject*)AsyncFunctionDef_type) < 0) return NULL;
|
||||
if (PyDict_SetItemString(d, "ClassDef", (PyObject*)ClassDef_type) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(d, "Return", (PyObject*)Return_type) < 0) return
|
||||
|
@ -6793,10 +7260,14 @@ PyInit__ast(void)
|
|||
if (PyDict_SetItemString(d, "AugAssign", (PyObject*)AugAssign_type) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(d, "For", (PyObject*)For_type) < 0) return NULL;
|
||||
if (PyDict_SetItemString(d, "AsyncFor", (PyObject*)AsyncFor_type) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(d, "While", (PyObject*)While_type) < 0) return
|
||||
NULL;
|
||||
if (PyDict_SetItemString(d, "If", (PyObject*)If_type) < 0) return NULL;
|
||||
if (PyDict_SetItemString(d, "With", (PyObject*)With_type) < 0) return NULL;
|
||||
if (PyDict_SetItemString(d, "AsyncWith", (PyObject*)AsyncWith_type) < 0)
|
||||
return NULL;
|
||||
if (PyDict_SetItemString(d, "Raise", (PyObject*)Raise_type) < 0) return
|
||||
NULL;
|
||||
if (PyDict_SetItemString(d, "Try", (PyObject*)Try_type) < 0) return NULL;
|
||||
|
@ -6837,6 +7308,8 @@ PyInit__ast(void)
|
|||
return NULL;
|
||||
if (PyDict_SetItemString(d, "GeneratorExp", (PyObject*)GeneratorExp_type) <
|
||||
0) return NULL;
|
||||
if (PyDict_SetItemString(d, "Await", (PyObject*)Await_type) < 0) return
|
||||
NULL;
|
||||
if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return
|
||||
NULL;
|
||||
if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) < 0)
|
||||
|
|
174
Python/ast.c
174
Python/ast.c
|
@ -219,6 +219,8 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
|
|||
return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
|
||||
case YieldFrom_kind:
|
||||
return validate_expr(exp->v.YieldFrom.value, Load);
|
||||
case Await_kind:
|
||||
return validate_expr(exp->v.Await.value, Load);
|
||||
case Compare_kind:
|
||||
if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
|
||||
PyErr_SetString(PyExc_ValueError, "Compare with no comparators");
|
||||
|
@ -336,6 +338,11 @@ validate_stmt(stmt_ty stmt)
|
|||
validate_expr(stmt->v.For.iter, Load) &&
|
||||
validate_body(stmt->v.For.body, "For") &&
|
||||
validate_stmts(stmt->v.For.orelse);
|
||||
case AsyncFor_kind:
|
||||
return validate_expr(stmt->v.AsyncFor.target, Store) &&
|
||||
validate_expr(stmt->v.AsyncFor.iter, Load) &&
|
||||
validate_body(stmt->v.AsyncFor.body, "AsyncFor") &&
|
||||
validate_stmts(stmt->v.AsyncFor.orelse);
|
||||
case While_kind:
|
||||
return validate_expr(stmt->v.While.test, Load) &&
|
||||
validate_body(stmt->v.While.body, "While") &&
|
||||
|
@ -354,6 +361,16 @@ validate_stmt(stmt_ty stmt)
|
|||
return 0;
|
||||
}
|
||||
return validate_body(stmt->v.With.body, "With");
|
||||
case AsyncWith_kind:
|
||||
if (!validate_nonempty_seq(stmt->v.AsyncWith.items, "items", "AsyncWith"))
|
||||
return 0;
|
||||
for (i = 0; i < asdl_seq_LEN(stmt->v.AsyncWith.items); i++) {
|
||||
withitem_ty item = asdl_seq_GET(stmt->v.AsyncWith.items, i);
|
||||
if (!validate_expr(item->context_expr, Load) ||
|
||||
(item->optional_vars && !validate_expr(item->optional_vars, Store)))
|
||||
return 0;
|
||||
}
|
||||
return validate_body(stmt->v.AsyncWith.body, "AsyncWith");
|
||||
case Raise_kind:
|
||||
if (stmt->v.Raise.exc) {
|
||||
return validate_expr(stmt->v.Raise.exc, Load) &&
|
||||
|
@ -405,6 +422,12 @@ validate_stmt(stmt_ty stmt)
|
|||
return validate_nonempty_seq(stmt->v.Nonlocal.names, "names", "Nonlocal");
|
||||
case Expr_kind:
|
||||
return validate_expr(stmt->v.Expr.value, Load);
|
||||
case AsyncFunctionDef_kind:
|
||||
return validate_body(stmt->v.AsyncFunctionDef.body, "AsyncFunctionDef") &&
|
||||
validate_arguments(stmt->v.AsyncFunctionDef.args) &&
|
||||
validate_exprs(stmt->v.AsyncFunctionDef.decorator_list, Load, 0) &&
|
||||
(!stmt->v.AsyncFunctionDef.returns ||
|
||||
validate_expr(stmt->v.AsyncFunctionDef.returns, Load));
|
||||
case Pass_kind:
|
||||
case Break_kind:
|
||||
case Continue_kind:
|
||||
|
@ -503,6 +526,9 @@ static asdl_seq *ast_for_exprlist(struct compiling *, const node *,
|
|||
static expr_ty ast_for_testlist(struct compiling *, const node *);
|
||||
static stmt_ty ast_for_classdef(struct compiling *, const node *, asdl_seq *);
|
||||
|
||||
static stmt_ty ast_for_with_stmt(struct compiling *, const node *, int);
|
||||
static stmt_ty ast_for_for_stmt(struct compiling *, const node *, int);
|
||||
|
||||
/* Note different signature for ast_for_call */
|
||||
static expr_ty ast_for_call(struct compiling *, const node *, expr_ty);
|
||||
|
||||
|
@ -941,6 +967,9 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
|
|||
case YieldFrom_kind:
|
||||
expr_name = "yield expression";
|
||||
break;
|
||||
case Await_kind:
|
||||
expr_name = "await expression";
|
||||
break;
|
||||
case ListComp_kind:
|
||||
expr_name = "list comprehension";
|
||||
break;
|
||||
|
@ -1480,7 +1509,8 @@ ast_for_decorators(struct compiling *c, const node *n)
|
|||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
||||
ast_for_funcdef_impl(struct compiling *c, const node *n,
|
||||
asdl_seq *decorator_seq, int is_async)
|
||||
{
|
||||
/* funcdef: 'def' NAME parameters ['->' test] ':' suite */
|
||||
identifier name;
|
||||
|
@ -1509,14 +1539,68 @@ ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
|||
if (!body)
|
||||
return NULL;
|
||||
|
||||
return FunctionDef(name, args, body, decorator_seq, returns, LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
if (is_async)
|
||||
return AsyncFunctionDef(name, args, body, decorator_seq, returns,
|
||||
LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
else
|
||||
return FunctionDef(name, args, body, decorator_seq, returns,
|
||||
LINENO(n),
|
||||
n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_async_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
||||
{
|
||||
/* async_funcdef: ASYNC funcdef */
|
||||
REQ(n, async_funcdef);
|
||||
REQ(CHILD(n, 0), ASYNC);
|
||||
REQ(CHILD(n, 1), funcdef);
|
||||
|
||||
return ast_for_funcdef_impl(c, CHILD(n, 1), decorator_seq,
|
||||
1 /* is_async */);
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_funcdef(struct compiling *c, const node *n, asdl_seq *decorator_seq)
|
||||
{
|
||||
/* funcdef: 'def' NAME parameters ['->' test] ':' suite */
|
||||
return ast_for_funcdef_impl(c, n, decorator_seq,
|
||||
0 /* is_async */);
|
||||
}
|
||||
|
||||
|
||||
static stmt_ty
|
||||
ast_for_async_stmt(struct compiling *c, const node *n)
|
||||
{
|
||||
/* async_stmt: ASYNC (funcdef | with_stmt | for_stmt) */
|
||||
REQ(n, async_stmt);
|
||||
REQ(CHILD(n, 0), ASYNC);
|
||||
|
||||
switch (TYPE(CHILD(n, 1))) {
|
||||
case funcdef:
|
||||
return ast_for_funcdef_impl(c, CHILD(n, 1), NULL,
|
||||
1 /* is_async */);
|
||||
case with_stmt:
|
||||
return ast_for_with_stmt(c, CHILD(n, 1),
|
||||
1 /* is_async */);
|
||||
|
||||
case for_stmt:
|
||||
return ast_for_for_stmt(c, CHILD(n, 1),
|
||||
1 /* is_async */);
|
||||
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"invalid async stament: %s",
|
||||
STR(CHILD(n, 1)));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_decorated(struct compiling *c, const node *n)
|
||||
{
|
||||
/* decorated: decorators (classdef | funcdef) */
|
||||
/* decorated: decorators (classdef | funcdef | async_funcdef) */
|
||||
stmt_ty thing = NULL;
|
||||
asdl_seq *decorator_seq = NULL;
|
||||
|
||||
|
@ -1527,12 +1611,15 @@ ast_for_decorated(struct compiling *c, const node *n)
|
|||
return NULL;
|
||||
|
||||
assert(TYPE(CHILD(n, 1)) == funcdef ||
|
||||
TYPE(CHILD(n, 1)) == async_funcdef ||
|
||||
TYPE(CHILD(n, 1)) == classdef);
|
||||
|
||||
if (TYPE(CHILD(n, 1)) == funcdef) {
|
||||
thing = ast_for_funcdef(c, CHILD(n, 1), decorator_seq);
|
||||
} else if (TYPE(CHILD(n, 1)) == classdef) {
|
||||
thing = ast_for_classdef(c, CHILD(n, 1), decorator_seq);
|
||||
} else if (TYPE(CHILD(n, 1)) == async_funcdef) {
|
||||
thing = ast_for_async_funcdef(c, CHILD(n, 1), decorator_seq);
|
||||
}
|
||||
/* we count the decorators in when talking about the class' or
|
||||
* function's line number */
|
||||
|
@ -2271,19 +2358,29 @@ ast_for_factor(struct compiling *c, const node *n)
|
|||
}
|
||||
|
||||
static expr_ty
|
||||
ast_for_power(struct compiling *c, const node *n)
|
||||
ast_for_atom_expr(struct compiling *c, const node *n)
|
||||
{
|
||||
/* power: atom trailer* ('**' factor)*
|
||||
*/
|
||||
int i;
|
||||
int i, nch, start = 0;
|
||||
expr_ty e, tmp;
|
||||
REQ(n, power);
|
||||
e = ast_for_atom(c, CHILD(n, 0));
|
||||
|
||||
REQ(n, atom_expr);
|
||||
nch = NCH(n);
|
||||
|
||||
if (TYPE(CHILD(n, 0)) == AWAIT) {
|
||||
start = 1;
|
||||
assert(nch > 1);
|
||||
}
|
||||
|
||||
e = ast_for_atom(c, CHILD(n, start));
|
||||
if (!e)
|
||||
return NULL;
|
||||
if (NCH(n) == 1)
|
||||
if (nch == 1)
|
||||
return e;
|
||||
for (i = 1; i < NCH(n); i++) {
|
||||
if (start && nch == 2) {
|
||||
return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
for (i = start + 1; i < nch; i++) {
|
||||
node *ch = CHILD(n, i);
|
||||
if (TYPE(ch) != trailer)
|
||||
break;
|
||||
|
@ -2294,6 +2391,28 @@ ast_for_power(struct compiling *c, const node *n)
|
|||
tmp->col_offset = e->col_offset;
|
||||
e = tmp;
|
||||
}
|
||||
|
||||
if (start) {
|
||||
/* there was an AWAIT */
|
||||
return Await(e, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
else {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
|
||||
static expr_ty
|
||||
ast_for_power(struct compiling *c, const node *n)
|
||||
{
|
||||
/* power: atom trailer* ('**' factor)*
|
||||
*/
|
||||
expr_ty e;
|
||||
REQ(n, power);
|
||||
e = ast_for_atom_expr(c, CHILD(n, 0));
|
||||
if (!e)
|
||||
return NULL;
|
||||
if (NCH(n) == 1)
|
||||
return e;
|
||||
if (TYPE(CHILD(n, NCH(n) - 1)) == factor) {
|
||||
expr_ty f = ast_for_expr(c, CHILD(n, NCH(n) - 1));
|
||||
if (!f)
|
||||
|
@ -2338,7 +2457,9 @@ ast_for_expr(struct compiling *c, const node *n)
|
|||
arith_expr: term (('+'|'-') term)*
|
||||
term: factor (('*'|'@'|'/'|'%'|'//') factor)*
|
||||
factor: ('+'|'-'|'~') factor | power
|
||||
power: atom trailer* ('**' factor)*
|
||||
power: atom_expr ['**' factor]
|
||||
atom_expr: [AWAIT] atom trailer*
|
||||
yield_expr: 'yield' [yield_arg]
|
||||
*/
|
||||
|
||||
asdl_seq *seq;
|
||||
|
@ -3403,7 +3524,7 @@ ast_for_while_stmt(struct compiling *c, const node *n)
|
|||
}
|
||||
|
||||
static stmt_ty
|
||||
ast_for_for_stmt(struct compiling *c, const node *n)
|
||||
ast_for_for_stmt(struct compiling *c, const node *n, int is_async)
|
||||
{
|
||||
asdl_seq *_target, *seq = NULL, *suite_seq;
|
||||
expr_ty expression;
|
||||
|
@ -3437,8 +3558,14 @@ ast_for_for_stmt(struct compiling *c, const node *n)
|
|||
if (!suite_seq)
|
||||
return NULL;
|
||||
|
||||
return For(target, expression, suite_seq, seq, LINENO(n), n->n_col_offset,
|
||||
c->c_arena);
|
||||
if (is_async)
|
||||
return AsyncFor(target, expression, suite_seq, seq,
|
||||
LINENO(n), n->n_col_offset,
|
||||
c->c_arena);
|
||||
else
|
||||
return For(target, expression, suite_seq, seq,
|
||||
LINENO(n), n->n_col_offset,
|
||||
c->c_arena);
|
||||
}
|
||||
|
||||
static excepthandler_ty
|
||||
|
@ -3585,7 +3712,7 @@ ast_for_with_item(struct compiling *c, const node *n)
|
|||
|
||||
/* with_stmt: 'with' with_item (',' with_item)* ':' suite */
|
||||
static stmt_ty
|
||||
ast_for_with_stmt(struct compiling *c, const node *n)
|
||||
ast_for_with_stmt(struct compiling *c, const node *n, int is_async)
|
||||
{
|
||||
int i, n_items;
|
||||
asdl_seq *items, *body;
|
||||
|
@ -3607,7 +3734,10 @@ ast_for_with_stmt(struct compiling *c, const node *n)
|
|||
if (!body)
|
||||
return NULL;
|
||||
|
||||
return With(items, body, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
if (is_async)
|
||||
return AsyncWith(items, body, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
else
|
||||
return With(items, body, LINENO(n), n->n_col_offset, c->c_arena);
|
||||
}
|
||||
|
||||
static stmt_ty
|
||||
|
@ -3714,7 +3844,7 @@ ast_for_stmt(struct compiling *c, const node *n)
|
|||
}
|
||||
else {
|
||||
/* compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt
|
||||
| funcdef | classdef | decorated
|
||||
| funcdef | classdef | decorated | async_stmt
|
||||
*/
|
||||
node *ch = CHILD(n, 0);
|
||||
REQ(n, compound_stmt);
|
||||
|
@ -3724,17 +3854,19 @@ ast_for_stmt(struct compiling *c, const node *n)
|
|||
case while_stmt:
|
||||
return ast_for_while_stmt(c, ch);
|
||||
case for_stmt:
|
||||
return ast_for_for_stmt(c, ch);
|
||||
return ast_for_for_stmt(c, ch, 0);
|
||||
case try_stmt:
|
||||
return ast_for_try_stmt(c, ch);
|
||||
case with_stmt:
|
||||
return ast_for_with_stmt(c, ch);
|
||||
return ast_for_with_stmt(c, ch, 0);
|
||||
case funcdef:
|
||||
return ast_for_funcdef(c, ch, NULL);
|
||||
case classdef:
|
||||
return ast_for_classdef(c, ch, NULL);
|
||||
case decorated:
|
||||
return ast_for_decorated(c, ch);
|
||||
case async_stmt:
|
||||
return ast_for_async_stmt(c, ch);
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"unhandled small_stmt: TYPE=%d NCH=%d\n",
|
||||
|
|
231
Python/ceval.c
231
Python/ceval.c
|
@ -1926,11 +1926,133 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
goto fast_block_end;
|
||||
}
|
||||
|
||||
TARGET(GET_AITER) {
|
||||
getaiterfunc getter = NULL;
|
||||
PyObject *iter = NULL;
|
||||
PyObject *awaitable = NULL;
|
||||
PyObject *obj = TOP();
|
||||
PyTypeObject *type = Py_TYPE(obj);
|
||||
|
||||
if (type->tp_as_async != NULL)
|
||||
getter = type->tp_as_async->am_aiter;
|
||||
|
||||
if (getter != NULL) {
|
||||
iter = (*getter)(obj);
|
||||
Py_DECREF(obj);
|
||||
if (iter == NULL) {
|
||||
SET_TOP(NULL);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
SET_TOP(NULL);
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"'async for' requires an object with "
|
||||
"__aiter__ method, got %.100s",
|
||||
type->tp_name);
|
||||
Py_DECREF(obj);
|
||||
goto error;
|
||||
}
|
||||
|
||||
awaitable = _PyGen_GetAwaitableIter(iter);
|
||||
if (awaitable == NULL) {
|
||||
SET_TOP(NULL);
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"'async for' received an invalid object "
|
||||
"from __aiter__: %.100s",
|
||||
Py_TYPE(iter)->tp_name);
|
||||
|
||||
Py_DECREF(iter);
|
||||
goto error;
|
||||
} else
|
||||
Py_DECREF(iter);
|
||||
|
||||
SET_TOP(awaitable);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(GET_ANEXT) {
|
||||
aiternextfunc getter = NULL;
|
||||
PyObject *next_iter = NULL;
|
||||
PyObject *awaitable = NULL;
|
||||
PyObject *aiter = TOP();
|
||||
PyTypeObject *type = Py_TYPE(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) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"'async for' requires an iterator with "
|
||||
"__anext__ method, got %.100s",
|
||||
type->tp_name);
|
||||
goto error;
|
||||
}
|
||||
|
||||
awaitable = _PyGen_GetAwaitableIter(next_iter);
|
||||
if (awaitable == NULL) {
|
||||
PyErr_Format(
|
||||
PyExc_TypeError,
|
||||
"'async for' received an invalid object "
|
||||
"from __anext__: %.100s",
|
||||
Py_TYPE(next_iter)->tp_name);
|
||||
|
||||
Py_DECREF(next_iter);
|
||||
goto error;
|
||||
} else
|
||||
Py_DECREF(next_iter);
|
||||
|
||||
PUSH(awaitable);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(GET_AWAITABLE) {
|
||||
PyObject *iterable = TOP();
|
||||
PyObject *iter = _PyGen_GetAwaitableIter(iterable);
|
||||
|
||||
Py_DECREF(iterable);
|
||||
|
||||
SET_TOP(iter); /* Even if it's NULL */
|
||||
|
||||
if (iter == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(YIELD_FROM) {
|
||||
PyObject *v = POP();
|
||||
PyObject *reciever = TOP();
|
||||
int err;
|
||||
if (PyGen_CheckExact(reciever)) {
|
||||
if (
|
||||
(((PyCodeObject*) \
|
||||
((PyGenObject*)reciever)->gi_code)->co_flags &
|
||||
CO_COROUTINE)
|
||||
&& !(co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)))
|
||||
{
|
||||
/* If we're yielding-from a coroutine object from a regular
|
||||
generator object - raise an error. */
|
||||
|
||||
Py_CLEAR(v);
|
||||
Py_CLEAR(reciever);
|
||||
SET_TOP(NULL);
|
||||
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"cannot 'yield from' a coroutine object "
|
||||
"from a generator");
|
||||
goto error;
|
||||
}
|
||||
retval = _PyGen_Send((PyGenObject *)reciever, v);
|
||||
} else {
|
||||
_Py_IDENTIFIER(send);
|
||||
|
@ -2822,11 +2944,26 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
TARGET(GET_ITER) {
|
||||
/* before: [obj]; after [getiter(obj)] */
|
||||
PyObject *iterable = TOP();
|
||||
PyObject *iter = PyObject_GetIter(iterable);
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(iter);
|
||||
if (iter == NULL)
|
||||
goto error;
|
||||
PyObject *iter;
|
||||
/* If we have a generator object on top -- keep it there,
|
||||
it's already an iterator.
|
||||
|
||||
This is needed to allow use of 'async def' coroutines
|
||||
in 'yield from' expression from generator-based coroutines
|
||||
(decorated with types.coroutine()).
|
||||
|
||||
'yield from' is compiled to GET_ITER..YIELD_FROM combination,
|
||||
but since coroutines raise TypeError in their 'tp_iter' we
|
||||
need a way for them to "pass through" the GET_ITER.
|
||||
*/
|
||||
if (!PyGen_CheckExact(iterable)) {
|
||||
/* `iterable` is not a generator. */
|
||||
iter = PyObject_GetIter(iterable);
|
||||
Py_DECREF(iterable);
|
||||
SET_TOP(iter);
|
||||
if (iter == NULL)
|
||||
goto error;
|
||||
}
|
||||
PREDICT(FOR_ITER);
|
||||
DISPATCH();
|
||||
}
|
||||
|
@ -2883,6 +3020,39 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BEFORE_ASYNC_WITH) {
|
||||
_Py_IDENTIFIER(__aexit__);
|
||||
_Py_IDENTIFIER(__aenter__);
|
||||
|
||||
PyObject *mgr = TOP();
|
||||
PyObject *exit = special_lookup(mgr, &PyId___aexit__),
|
||||
*enter;
|
||||
PyObject *res;
|
||||
if (exit == NULL)
|
||||
goto error;
|
||||
SET_TOP(exit);
|
||||
enter = special_lookup(mgr, &PyId___aenter__);
|
||||
Py_DECREF(mgr);
|
||||
if (enter == NULL)
|
||||
goto error;
|
||||
res = PyObject_CallFunctionObjArgs(enter, NULL);
|
||||
Py_DECREF(enter);
|
||||
if (res == NULL)
|
||||
goto error;
|
||||
PUSH(res);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(SETUP_ASYNC_WITH) {
|
||||
PyObject *res = POP();
|
||||
/* Setup the finally block before pushing the result
|
||||
of __aenter__ on the stack. */
|
||||
PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg,
|
||||
STACK_LEVEL());
|
||||
PUSH(res);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(SETUP_WITH) {
|
||||
_Py_IDENTIFIER(__exit__);
|
||||
_Py_IDENTIFIER(__enter__);
|
||||
|
@ -2909,7 +3079,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(WITH_CLEANUP) {
|
||||
TARGET(WITH_CLEANUP_START) {
|
||||
/* At the top of the stack are 1-6 values indicating
|
||||
how/why we entered the finally clause:
|
||||
- TOP = None
|
||||
|
@ -2937,7 +3107,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
|
||||
PyObject *exit_func;
|
||||
PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res;
|
||||
int err;
|
||||
if (exc == Py_None) {
|
||||
(void)POP();
|
||||
exit_func = TOP();
|
||||
|
@ -2987,10 +3156,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
|
|||
if (res == NULL)
|
||||
goto error;
|
||||
|
||||
PUSH(exc);
|
||||
PUSH(res);
|
||||
PREDICT(WITH_CLEANUP_FINISH);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
PREDICTED(WITH_CLEANUP_FINISH);
|
||||
TARGET(WITH_CLEANUP_FINISH) {
|
||||
PyObject *res = POP();
|
||||
PyObject *exc = POP();
|
||||
int err;
|
||||
|
||||
if (exc != Py_None)
|
||||
err = PyObject_IsTrue(res);
|
||||
else
|
||||
err = 0;
|
||||
|
||||
Py_DECREF(res);
|
||||
|
||||
if (err < 0)
|
||||
|
@ -3751,6 +3933,9 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
}
|
||||
|
||||
if (co->co_flags & CO_GENERATOR) {
|
||||
PyObject *gen;
|
||||
PyObject *coroutine_wrapper;
|
||||
|
||||
/* Don't need to keep the reference to f_back, it will be set
|
||||
* when the generator is resumed. */
|
||||
Py_CLEAR(f->f_back);
|
||||
|
@ -3759,7 +3944,19 @@ _PyEval_EvalCodeWithName(PyObject *_co, PyObject *globals, PyObject *locals,
|
|||
|
||||
/* Create a new generator that owns the ready to run frame
|
||||
* and return that as the value. */
|
||||
return PyGen_NewWithQualName(f, name, qualname);
|
||||
gen = PyGen_NewWithQualName(f, name, qualname);
|
||||
if (gen == NULL)
|
||||
return NULL;
|
||||
|
||||
if (co->co_flags & (CO_COROUTINE | CO_ITERABLE_COROUTINE)) {
|
||||
coroutine_wrapper = PyEval_GetCoroutineWrapper();
|
||||
if (coroutine_wrapper != NULL) {
|
||||
PyObject *wrapped =
|
||||
PyObject_CallFunction(coroutine_wrapper, "N", gen);
|
||||
gen = wrapped;
|
||||
}
|
||||
}
|
||||
return gen;
|
||||
}
|
||||
|
||||
retval = PyEval_EvalFrameEx(f,0);
|
||||
|
@ -4205,6 +4402,24 @@ PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
|
|||
|| (tstate->c_profilefunc != NULL));
|
||||
}
|
||||
|
||||
void
|
||||
PyEval_SetCoroutineWrapper(PyObject *wrapper)
|
||||
{
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
|
||||
Py_CLEAR(tstate->coroutine_wrapper);
|
||||
|
||||
Py_XINCREF(wrapper);
|
||||
tstate->coroutine_wrapper = wrapper;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyEval_GetCoroutineWrapper()
|
||||
{
|
||||
PyThreadState *tstate = PyThreadState_GET();
|
||||
return tstate->coroutine_wrapper;
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyEval_GetBuiltins(void)
|
||||
{
|
||||
|
|
288
Python/compile.c
288
Python/compile.c
|
@ -92,6 +92,7 @@ enum {
|
|||
COMPILER_SCOPE_MODULE,
|
||||
COMPILER_SCOPE_CLASS,
|
||||
COMPILER_SCOPE_FUNCTION,
|
||||
COMPILER_SCOPE_ASYNC_FUNCTION,
|
||||
COMPILER_SCOPE_LAMBDA,
|
||||
COMPILER_SCOPE_COMPREHENSION,
|
||||
};
|
||||
|
@ -193,6 +194,8 @@ static int inplace_binop(struct compiler *, operator_ty);
|
|||
static int expr_constant(struct compiler *, expr_ty);
|
||||
|
||||
static int compiler_with(struct compiler *, stmt_ty, int);
|
||||
static int compiler_async_with(struct compiler *, stmt_ty, int);
|
||||
static int compiler_async_for(struct compiler *, stmt_ty);
|
||||
static int compiler_call_helper(struct compiler *c, Py_ssize_t n,
|
||||
asdl_seq *args,
|
||||
asdl_seq *keywords);
|
||||
|
@ -673,7 +676,9 @@ compiler_set_qualname(struct compiler *c)
|
|||
parent = (struct compiler_unit *)PyCapsule_GetPointer(capsule, CAPSULE_NAME);
|
||||
assert(parent);
|
||||
|
||||
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION || u->u_scope_type == COMPILER_SCOPE_CLASS) {
|
||||
if (u->u_scope_type == COMPILER_SCOPE_FUNCTION
|
||||
|| u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
|
||||
|| u->u_scope_type == COMPILER_SCOPE_CLASS) {
|
||||
assert(u->u_name);
|
||||
mangled = _Py_Mangle(parent->u_private, u->u_name);
|
||||
if (!mangled)
|
||||
|
@ -687,6 +692,7 @@ compiler_set_qualname(struct compiler *c)
|
|||
|
||||
if (!force_global) {
|
||||
if (parent->u_scope_type == COMPILER_SCOPE_FUNCTION
|
||||
|| parent->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION
|
||||
|| parent->u_scope_type == COMPILER_SCOPE_LAMBDA) {
|
||||
dot_locals_str = _PyUnicode_FromId(&dot_locals);
|
||||
if (dot_locals_str == NULL)
|
||||
|
@ -927,7 +933,9 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
|
|||
return 0;
|
||||
case SETUP_WITH:
|
||||
return 7;
|
||||
case WITH_CLEANUP:
|
||||
case WITH_CLEANUP_START:
|
||||
return 1;
|
||||
case WITH_CLEANUP_FINISH:
|
||||
return -1; /* XXX Sometimes more */
|
||||
case RETURN_VALUE:
|
||||
return -1;
|
||||
|
@ -1048,6 +1056,16 @@ PyCompile_OpcodeStackEffect(int opcode, int oparg)
|
|||
return -1;
|
||||
case DELETE_DEREF:
|
||||
return 0;
|
||||
case GET_AWAITABLE:
|
||||
return 0;
|
||||
case SETUP_ASYNC_WITH:
|
||||
return 6;
|
||||
case BEFORE_ASYNC_WITH:
|
||||
return 1;
|
||||
case GET_AITER:
|
||||
return 0;
|
||||
case GET_ANEXT:
|
||||
return 1;
|
||||
default:
|
||||
return PY_INVALID_STACK_EFFECT;
|
||||
}
|
||||
|
@ -1642,19 +1660,43 @@ error:
|
|||
}
|
||||
|
||||
static int
|
||||
compiler_function(struct compiler *c, stmt_ty s)
|
||||
compiler_function(struct compiler *c, stmt_ty s, int is_async)
|
||||
{
|
||||
PyCodeObject *co;
|
||||
PyObject *qualname, *first_const = Py_None;
|
||||
arguments_ty args = s->v.FunctionDef.args;
|
||||
expr_ty returns = s->v.FunctionDef.returns;
|
||||
asdl_seq* decos = s->v.FunctionDef.decorator_list;
|
||||
arguments_ty args;
|
||||
expr_ty returns;
|
||||
identifier name;
|
||||
asdl_seq* decos;
|
||||
asdl_seq *body;
|
||||
stmt_ty st;
|
||||
Py_ssize_t i, n, arglength;
|
||||
int docstring, kw_default_count = 0;
|
||||
int num_annotations;
|
||||
int scope_type;
|
||||
|
||||
assert(s->kind == FunctionDef_kind);
|
||||
|
||||
if (is_async) {
|
||||
assert(s->kind == AsyncFunctionDef_kind);
|
||||
|
||||
args = s->v.AsyncFunctionDef.args;
|
||||
returns = s->v.AsyncFunctionDef.returns;
|
||||
decos = s->v.AsyncFunctionDef.decorator_list;
|
||||
name = s->v.AsyncFunctionDef.name;
|
||||
body = s->v.AsyncFunctionDef.body;
|
||||
|
||||
scope_type = COMPILER_SCOPE_ASYNC_FUNCTION;
|
||||
} else {
|
||||
assert(s->kind == FunctionDef_kind);
|
||||
|
||||
args = s->v.FunctionDef.args;
|
||||
returns = s->v.FunctionDef.returns;
|
||||
decos = s->v.FunctionDef.decorator_list;
|
||||
name = s->v.FunctionDef.name;
|
||||
body = s->v.FunctionDef.body;
|
||||
|
||||
scope_type = COMPILER_SCOPE_FUNCTION;
|
||||
}
|
||||
|
||||
if (!compiler_decorators(c, decos))
|
||||
return 0;
|
||||
|
@ -1672,12 +1714,12 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
return 0;
|
||||
assert((num_annotations & 0xFFFF) == num_annotations);
|
||||
|
||||
if (!compiler_enter_scope(c, s->v.FunctionDef.name,
|
||||
COMPILER_SCOPE_FUNCTION, (void *)s,
|
||||
if (!compiler_enter_scope(c, name,
|
||||
scope_type, (void *)s,
|
||||
s->lineno))
|
||||
return 0;
|
||||
|
||||
st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, 0);
|
||||
st = (stmt_ty)asdl_seq_GET(body, 0);
|
||||
docstring = compiler_isdocstring(st);
|
||||
if (docstring && c->c_optimize < 2)
|
||||
first_const = st->v.Expr.value->v.Str.s;
|
||||
|
@ -1688,10 +1730,10 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
|
||||
c->u->u_argcount = asdl_seq_LEN(args->args);
|
||||
c->u->u_kwonlyargcount = asdl_seq_LEN(args->kwonlyargs);
|
||||
n = asdl_seq_LEN(s->v.FunctionDef.body);
|
||||
n = asdl_seq_LEN(body);
|
||||
/* if there was a docstring, we need to skip the first statement */
|
||||
for (i = docstring; i < n; i++) {
|
||||
st = (stmt_ty)asdl_seq_GET(s->v.FunctionDef.body, i);
|
||||
st = (stmt_ty)asdl_seq_GET(body, i);
|
||||
VISIT_IN_SCOPE(c, stmt, st);
|
||||
}
|
||||
co = assemble(c, 1);
|
||||
|
@ -1711,12 +1753,19 @@ compiler_function(struct compiler *c, stmt_ty s)
|
|||
Py_DECREF(qualname);
|
||||
Py_DECREF(co);
|
||||
|
||||
if (is_async) {
|
||||
co->co_flags |= CO_COROUTINE;
|
||||
/* An async function is always a generator, even
|
||||
if there is no 'yield' expressions in it. */
|
||||
co->co_flags |= CO_GENERATOR;
|
||||
}
|
||||
|
||||
/* decorators */
|
||||
for (i = 0; i < asdl_seq_LEN(decos); i++) {
|
||||
ADDOP_I(c, CALL_FUNCTION, 1);
|
||||
}
|
||||
|
||||
return compiler_nameop(c, s->v.FunctionDef.name, Store);
|
||||
return compiler_nameop(c, name, Store);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1989,6 +2038,92 @@ compiler_for(struct compiler *c, stmt_ty s)
|
|||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
compiler_async_for(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
static PyObject *stopiter_error = NULL;
|
||||
basicblock *try, *except, *end, *after_try, *try_cleanup,
|
||||
*after_loop, *after_loop_else;
|
||||
|
||||
if (stopiter_error == NULL) {
|
||||
stopiter_error = PyUnicode_InternFromString("StopAsyncIteration");
|
||||
if (stopiter_error == NULL)
|
||||
return 0;
|
||||
}
|
||||
|
||||
try = compiler_new_block(c);
|
||||
except = compiler_new_block(c);
|
||||
end = compiler_new_block(c);
|
||||
after_try = compiler_new_block(c);
|
||||
try_cleanup = compiler_new_block(c);
|
||||
after_loop = compiler_new_block(c);
|
||||
after_loop_else = compiler_new_block(c);
|
||||
|
||||
if (try == NULL || except == NULL || end == NULL
|
||||
|| after_try == NULL || try_cleanup == NULL)
|
||||
return 0;
|
||||
|
||||
ADDOP_JREL(c, SETUP_LOOP, after_loop);
|
||||
if (!compiler_push_fblock(c, LOOP, try))
|
||||
return 0;
|
||||
|
||||
VISIT(c, expr, s->v.AsyncFor.iter);
|
||||
ADDOP(c, GET_AITER);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
|
||||
compiler_use_next_block(c, try);
|
||||
|
||||
|
||||
ADDOP_JREL(c, SETUP_EXCEPT, except);
|
||||
if (!compiler_push_fblock(c, EXCEPT, try))
|
||||
return 0;
|
||||
|
||||
ADDOP(c, GET_ANEXT);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
VISIT(c, expr, s->v.AsyncFor.target);
|
||||
ADDOP(c, POP_BLOCK);
|
||||
compiler_pop_fblock(c, EXCEPT, try);
|
||||
ADDOP_JREL(c, JUMP_FORWARD, after_try);
|
||||
|
||||
|
||||
compiler_use_next_block(c, except);
|
||||
ADDOP(c, DUP_TOP);
|
||||
ADDOP_O(c, LOAD_GLOBAL, stopiter_error, names);
|
||||
ADDOP_I(c, COMPARE_OP, PyCmp_EXC_MATCH);
|
||||
ADDOP_JABS(c, POP_JUMP_IF_FALSE, try_cleanup);
|
||||
|
||||
ADDOP(c, POP_TOP);
|
||||
ADDOP(c, POP_TOP);
|
||||
ADDOP(c, POP_TOP);
|
||||
ADDOP(c, POP_EXCEPT); /* for SETUP_EXCEPT */
|
||||
ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */
|
||||
ADDOP_JABS(c, JUMP_ABSOLUTE, after_loop_else);
|
||||
|
||||
|
||||
compiler_use_next_block(c, try_cleanup);
|
||||
ADDOP(c, END_FINALLY);
|
||||
|
||||
compiler_use_next_block(c, after_try);
|
||||
VISIT_SEQ(c, stmt, s->v.AsyncFor.body);
|
||||
ADDOP_JABS(c, JUMP_ABSOLUTE, try);
|
||||
|
||||
ADDOP(c, POP_BLOCK); /* for SETUP_LOOP */
|
||||
compiler_pop_fblock(c, LOOP, try);
|
||||
|
||||
compiler_use_next_block(c, after_loop);
|
||||
ADDOP_JABS(c, JUMP_ABSOLUTE, end);
|
||||
|
||||
compiler_use_next_block(c, after_loop_else);
|
||||
VISIT_SEQ(c, stmt, s->v.For.orelse);
|
||||
|
||||
compiler_use_next_block(c, end);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_while(struct compiler *c, stmt_ty s)
|
||||
{
|
||||
|
@ -2515,7 +2650,7 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
|||
|
||||
switch (s->kind) {
|
||||
case FunctionDef_kind:
|
||||
return compiler_function(c, s);
|
||||
return compiler_function(c, s, 0);
|
||||
case ClassDef_kind:
|
||||
return compiler_class(c, s);
|
||||
case Return_kind:
|
||||
|
@ -2594,7 +2729,14 @@ compiler_visit_stmt(struct compiler *c, stmt_ty s)
|
|||
return compiler_continue(c);
|
||||
case With_kind:
|
||||
return compiler_with(c, s, 0);
|
||||
case AsyncFunctionDef_kind:
|
||||
return compiler_function(c, s, 1);
|
||||
case AsyncWith_kind:
|
||||
return compiler_async_with(c, s, 0);
|
||||
case AsyncFor_kind:
|
||||
return compiler_async_for(c, s);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3471,6 +3613,102 @@ expr_constant(struct compiler *c, expr_ty e)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Implements the async with statement.
|
||||
|
||||
The semantics outlined in that PEP are as follows:
|
||||
|
||||
async with EXPR as VAR:
|
||||
BLOCK
|
||||
|
||||
It is implemented roughly as:
|
||||
|
||||
context = EXPR
|
||||
exit = context.__aexit__ # not calling it
|
||||
value = await context.__aenter__()
|
||||
try:
|
||||
VAR = value # if VAR present in the syntax
|
||||
BLOCK
|
||||
finally:
|
||||
if an exception was raised:
|
||||
exc = copy of (exception, instance, traceback)
|
||||
else:
|
||||
exc = (None, None, None)
|
||||
if not (await exit(*exc)):
|
||||
raise
|
||||
*/
|
||||
static int
|
||||
compiler_async_with(struct compiler *c, stmt_ty s, int pos)
|
||||
{
|
||||
basicblock *block, *finally;
|
||||
withitem_ty item = asdl_seq_GET(s->v.AsyncWith.items, pos);
|
||||
|
||||
assert(s->kind == AsyncWith_kind);
|
||||
|
||||
block = compiler_new_block(c);
|
||||
finally = compiler_new_block(c);
|
||||
if (!block || !finally)
|
||||
return 0;
|
||||
|
||||
/* Evaluate EXPR */
|
||||
VISIT(c, expr, item->context_expr);
|
||||
|
||||
ADDOP(c, BEFORE_ASYNC_WITH);
|
||||
ADDOP(c, GET_AWAITABLE);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
|
||||
ADDOP_JREL(c, SETUP_ASYNC_WITH, finally);
|
||||
|
||||
/* SETUP_ASYNC_WITH pushes a finally block. */
|
||||
compiler_use_next_block(c, block);
|
||||
if (!compiler_push_fblock(c, FINALLY_TRY, block)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (item->optional_vars) {
|
||||
VISIT(c, expr, item->optional_vars);
|
||||
}
|
||||
else {
|
||||
/* Discard result from context.__aenter__() */
|
||||
ADDOP(c, POP_TOP);
|
||||
}
|
||||
|
||||
pos++;
|
||||
if (pos == asdl_seq_LEN(s->v.AsyncWith.items))
|
||||
/* BLOCK code */
|
||||
VISIT_SEQ(c, stmt, s->v.AsyncWith.body)
|
||||
else if (!compiler_async_with(c, s, pos))
|
||||
return 0;
|
||||
|
||||
/* End of try block; start the finally block */
|
||||
ADDOP(c, POP_BLOCK);
|
||||
compiler_pop_fblock(c, FINALLY_TRY, block);
|
||||
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
compiler_use_next_block(c, finally);
|
||||
if (!compiler_push_fblock(c, FINALLY_END, finally))
|
||||
return 0;
|
||||
|
||||
/* Finally block starts; context.__exit__ is on the stack under
|
||||
the exception or return information. Just issue our magic
|
||||
opcode. */
|
||||
ADDOP(c, WITH_CLEANUP_START);
|
||||
|
||||
ADDOP(c, GET_AWAITABLE);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
|
||||
ADDOP(c, WITH_CLEANUP_FINISH);
|
||||
|
||||
/* Finally block ends. */
|
||||
ADDOP(c, END_FINALLY);
|
||||
compiler_pop_fblock(c, FINALLY_END, finally);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Implements the with statement from PEP 343.
|
||||
|
||||
|
@ -3544,7 +3782,8 @@ compiler_with(struct compiler *c, stmt_ty s, int pos)
|
|||
/* Finally block starts; context.__exit__ is on the stack under
|
||||
the exception or return information. Just issue our magic
|
||||
opcode. */
|
||||
ADDOP(c, WITH_CLEANUP);
|
||||
ADDOP(c, WITH_CLEANUP_START);
|
||||
ADDOP(c, WITH_CLEANUP_FINISH);
|
||||
|
||||
/* Finally block ends. */
|
||||
ADDOP(c, END_FINALLY);
|
||||
|
@ -3595,6 +3834,8 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
|||
case Yield_kind:
|
||||
if (c->u->u_ste->ste_type != FunctionBlock)
|
||||
return compiler_error(c, "'yield' outside function");
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION)
|
||||
return compiler_error(c, "'yield' inside async function");
|
||||
if (e->v.Yield.value) {
|
||||
VISIT(c, expr, e->v.Yield.value);
|
||||
}
|
||||
|
@ -3606,11 +3847,28 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
|
|||
case YieldFrom_kind:
|
||||
if (c->u->u_ste->ste_type != FunctionBlock)
|
||||
return compiler_error(c, "'yield' outside function");
|
||||
|
||||
if (c->u->u_scope_type == COMPILER_SCOPE_ASYNC_FUNCTION)
|
||||
return compiler_error(c, "'yield from' inside async function");
|
||||
|
||||
VISIT(c, expr, e->v.YieldFrom.value);
|
||||
ADDOP(c, GET_ITER);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
break;
|
||||
case Await_kind:
|
||||
if (c->u->u_ste->ste_type != FunctionBlock)
|
||||
return compiler_error(c, "'await' outside function");
|
||||
|
||||
/* this check won't be triggered while we have AWAIT token */
|
||||
if (c->u->u_scope_type != COMPILER_SCOPE_ASYNC_FUNCTION)
|
||||
return compiler_error(c, "'await' outside async function");
|
||||
|
||||
VISIT(c, expr, e->v.Await.value);
|
||||
ADDOP(c, GET_AWAITABLE);
|
||||
ADDOP_O(c, LOAD_CONST, Py_None, consts);
|
||||
ADDOP(c, YIELD_FROM);
|
||||
break;
|
||||
case Compare_kind:
|
||||
return compiler_compare(c, e);
|
||||
case Call_kind:
|
||||
|
|
2714
Python/graminit.c
2714
Python/graminit.c
File diff suppressed because it is too large
Load diff
3480
Python/importlib.h
3480
Python/importlib.h
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -49,9 +49,9 @@ static void *opcode_targets[256] = {
|
|||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_GET_AITER,
|
||||
&&TARGET_GET_ANEXT,
|
||||
&&TARGET_BEFORE_ASYNC_WITH,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_STORE_MAP,
|
||||
&&TARGET_INPLACE_ADD,
|
||||
|
@ -72,7 +72,7 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_PRINT_EXPR,
|
||||
&&TARGET_LOAD_BUILD_CLASS,
|
||||
&&TARGET_YIELD_FROM,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_GET_AWAITABLE,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_INPLACE_LSHIFT,
|
||||
&&TARGET_INPLACE_RSHIFT,
|
||||
|
@ -80,8 +80,8 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_INPLACE_XOR,
|
||||
&&TARGET_INPLACE_OR,
|
||||
&&TARGET_BREAK_LOOP,
|
||||
&&TARGET_WITH_CLEANUP,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_WITH_CLEANUP_START,
|
||||
&&TARGET_WITH_CLEANUP_FINISH,
|
||||
&&TARGET_RETURN_VALUE,
|
||||
&&TARGET_IMPORT_STAR,
|
||||
&&_unknown_opcode,
|
||||
|
@ -153,7 +153,7 @@ static void *opcode_targets[256] = {
|
|||
&&TARGET_BUILD_MAP_UNPACK_WITH_CALL,
|
||||
&&TARGET_BUILD_TUPLE_UNPACK,
|
||||
&&TARGET_BUILD_SET_UNPACK,
|
||||
&&_unknown_opcode,
|
||||
&&TARGET_SETUP_ASYNC_WITH,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
&&_unknown_opcode,
|
||||
|
|
|
@ -319,6 +319,7 @@ markblocks(unsigned char *code, Py_ssize_t len)
|
|||
case SETUP_EXCEPT:
|
||||
case SETUP_FINALLY:
|
||||
case SETUP_WITH:
|
||||
case SETUP_ASYNC_WITH:
|
||||
j = GETJUMPTGT(code, i);
|
||||
blocks[j] = 1;
|
||||
break;
|
||||
|
@ -620,6 +621,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case SETUP_EXCEPT:
|
||||
case SETUP_FINALLY:
|
||||
case SETUP_WITH:
|
||||
case SETUP_ASYNC_WITH:
|
||||
tgt = GETJUMPTGT(codestr, i);
|
||||
/* Replace JUMP_* to a RETURN into just a RETURN */
|
||||
if (UNCONDITIONAL_JUMP(opcode) &&
|
||||
|
@ -704,6 +706,7 @@ PyCode_Optimize(PyObject *code, PyObject* consts, PyObject *names,
|
|||
case SETUP_EXCEPT:
|
||||
case SETUP_FINALLY:
|
||||
case SETUP_WITH:
|
||||
case SETUP_ASYNC_WITH:
|
||||
j = addrmap[GETARG(codestr, i) + i + 3] - addrmap[i] - 3;
|
||||
SETARG(codestr, i, j);
|
||||
break;
|
||||
|
|
|
@ -212,6 +212,8 @@ new_threadstate(PyInterpreterState *interp, int init)
|
|||
tstate->on_delete = NULL;
|
||||
tstate->on_delete_data = NULL;
|
||||
|
||||
tstate->coroutine_wrapper = NULL;
|
||||
|
||||
if (init)
|
||||
_PyThreadState_Init(tstate);
|
||||
|
||||
|
@ -372,6 +374,8 @@ PyThreadState_Clear(PyThreadState *tstate)
|
|||
tstate->c_tracefunc = NULL;
|
||||
Py_CLEAR(tstate->c_profileobj);
|
||||
Py_CLEAR(tstate->c_traceobj);
|
||||
|
||||
Py_CLEAR(tstate->coroutine_wrapper);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -180,7 +180,7 @@ static int symtable_visit_slice(struct symtable *st, slice_ty);
|
|||
static int symtable_visit_params(struct symtable *st, asdl_seq *args);
|
||||
static int symtable_visit_argannotations(struct symtable *st, asdl_seq *args);
|
||||
static int symtable_implicit_arg(struct symtable *st, int pos);
|
||||
static int symtable_visit_annotations(struct symtable *st, stmt_ty s);
|
||||
static int symtable_visit_annotations(struct symtable *st, stmt_ty s, arguments_ty, expr_ty);
|
||||
static int symtable_visit_withitem(struct symtable *st, withitem_ty item);
|
||||
|
||||
|
||||
|
@ -1147,7 +1147,8 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, expr, s->v.FunctionDef.args->defaults);
|
||||
if (s->v.FunctionDef.args->kw_defaults)
|
||||
VISIT_SEQ_WITH_NULL(st, expr, s->v.FunctionDef.args->kw_defaults);
|
||||
if (!symtable_visit_annotations(st, s))
|
||||
if (!symtable_visit_annotations(st, s, s->v.FunctionDef.args,
|
||||
s->v.FunctionDef.returns))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.FunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.FunctionDef.decorator_list);
|
||||
|
@ -1315,6 +1316,39 @@ symtable_visit_stmt(struct symtable *st, stmt_ty s)
|
|||
VISIT_SEQ(st, withitem, s->v.With.items);
|
||||
VISIT_SEQ(st, stmt, s->v.With.body);
|
||||
break;
|
||||
case AsyncFunctionDef_kind:
|
||||
if (!symtable_add_def(st, s->v.AsyncFunctionDef.name, DEF_LOCAL))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.AsyncFunctionDef.args->defaults)
|
||||
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.args->defaults);
|
||||
if (s->v.AsyncFunctionDef.args->kw_defaults)
|
||||
VISIT_SEQ_WITH_NULL(st, expr,
|
||||
s->v.AsyncFunctionDef.args->kw_defaults);
|
||||
if (!symtable_visit_annotations(st, s, s->v.AsyncFunctionDef.args,
|
||||
s->v.AsyncFunctionDef.returns))
|
||||
VISIT_QUIT(st, 0);
|
||||
if (s->v.AsyncFunctionDef.decorator_list)
|
||||
VISIT_SEQ(st, expr, s->v.AsyncFunctionDef.decorator_list);
|
||||
if (!symtable_enter_block(st, s->v.AsyncFunctionDef.name,
|
||||
FunctionBlock, (void *)s, s->lineno,
|
||||
s->col_offset))
|
||||
VISIT_QUIT(st, 0);
|
||||
VISIT(st, arguments, s->v.AsyncFunctionDef.args);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFunctionDef.body);
|
||||
if (!symtable_exit_block(st, s))
|
||||
VISIT_QUIT(st, 0);
|
||||
break;
|
||||
case AsyncWith_kind:
|
||||
VISIT_SEQ(st, withitem, s->v.AsyncWith.items);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncWith.body);
|
||||
break;
|
||||
case AsyncFor_kind:
|
||||
VISIT(st, expr, s->v.AsyncFor.target);
|
||||
VISIT(st, expr, s->v.AsyncFor.iter);
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFor.body);
|
||||
if (s->v.AsyncFor.orelse)
|
||||
VISIT_SEQ(st, stmt, s->v.AsyncFor.orelse);
|
||||
break;
|
||||
}
|
||||
VISIT_QUIT(st, 1);
|
||||
}
|
||||
|
@ -1392,6 +1426,10 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
|
|||
VISIT(st, expr, e->v.YieldFrom.value);
|
||||
st->st_cur->ste_generator = 1;
|
||||
break;
|
||||
case Await_kind:
|
||||
VISIT(st, expr, e->v.Await.value);
|
||||
st->st_cur->ste_generator = 1;
|
||||
break;
|
||||
case Compare_kind:
|
||||
VISIT(st, expr, e->v.Compare.left);
|
||||
VISIT_SEQ(st, expr, e->v.Compare.comparators);
|
||||
|
@ -1492,10 +1530,9 @@ symtable_visit_argannotations(struct symtable *st, asdl_seq *args)
|
|||
}
|
||||
|
||||
static int
|
||||
symtable_visit_annotations(struct symtable *st, stmt_ty s)
|
||||
symtable_visit_annotations(struct symtable *st, stmt_ty s,
|
||||
arguments_ty a, expr_ty returns)
|
||||
{
|
||||
arguments_ty a = s->v.FunctionDef.args;
|
||||
|
||||
if (a->args && !symtable_visit_argannotations(st, a->args))
|
||||
return 0;
|
||||
if (a->vararg && a->vararg->annotation)
|
||||
|
@ -1504,7 +1541,7 @@ symtable_visit_annotations(struct symtable *st, stmt_ty s)
|
|||
VISIT(st, expr, a->kwarg->annotation);
|
||||
if (a->kwonlyargs && !symtable_visit_argannotations(st, a->kwonlyargs))
|
||||
return 0;
|
||||
if (s->v.FunctionDef.returns)
|
||||
if (returns)
|
||||
VISIT(st, expr, s->v.FunctionDef.returns);
|
||||
return 1;
|
||||
}
|
||||
|
|
|
@ -645,6 +645,49 @@ sys_setrecursionlimit(PyObject *self, PyObject *args)
|
|||
return Py_None;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
sys_set_coroutine_wrapper(PyObject *self, PyObject *wrapper)
|
||||
{
|
||||
if (wrapper != Py_None) {
|
||||
if (!PyCallable_Check(wrapper)) {
|
||||
PyErr_Format(PyExc_TypeError,
|
||||
"callable expected, got %.50s",
|
||||
Py_TYPE(wrapper)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PyEval_SetCoroutineWrapper(wrapper);
|
||||
}
|
||||
else
|
||||
PyEval_SetCoroutineWrapper(NULL);
|
||||
Py_INCREF(Py_None);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(set_coroutine_wrapper_doc,
|
||||
"set_coroutine_wrapper(wrapper)\n\
|
||||
\n\
|
||||
Set a wrapper for coroutine objects."
|
||||
);
|
||||
|
||||
static PyObject *
|
||||
sys_get_coroutine_wrapper(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *wrapper = PyEval_GetCoroutineWrapper();
|
||||
if (wrapper == NULL) {
|
||||
wrapper = Py_None;
|
||||
}
|
||||
Py_INCREF(wrapper);
|
||||
return wrapper;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(get_coroutine_wrapper_doc,
|
||||
"get_coroutine_wrapper()\n\
|
||||
\n\
|
||||
Return the wrapper for coroutine objects set by sys.set_coroutine_wrapper."
|
||||
);
|
||||
|
||||
|
||||
static PyTypeObject Hash_InfoType;
|
||||
|
||||
PyDoc_STRVAR(hash_info_doc,
|
||||
|
@ -1215,6 +1258,10 @@ static PyMethodDef sys_methods[] = {
|
|||
{"call_tracing", sys_call_tracing, METH_VARARGS, call_tracing_doc},
|
||||
{"_debugmallocstats", sys_debugmallocstats, METH_NOARGS,
|
||||
debugmallocstats_doc},
|
||||
{"set_coroutine_wrapper", sys_set_coroutine_wrapper, METH_O,
|
||||
set_coroutine_wrapper_doc},
|
||||
{"get_coroutine_wrapper", sys_get_coroutine_wrapper, METH_NOARGS,
|
||||
get_coroutine_wrapper_doc},
|
||||
{NULL, NULL} /* sentinel */
|
||||
};
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue