Skip to content

Commit 527c622

Browse files
committed
make YieldFrom its own distinct from Yield (closes #13780)
1 parent 91f252b commit 527c622

7 files changed

Lines changed: 84 additions & 32 deletions

File tree

‎Include/Python-ast.h‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ struct _stmt {
180180
enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
181181
IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
182182
SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
183-
Yield_kind=12, Compare_kind=13, Call_kind=14, Num_kind=15,
184-
Str_kind=16, Bytes_kind=17, Ellipsis_kind=18,
185-
Attribute_kind=19, Subscript_kind=20, Starred_kind=21,
186-
Name_kind=22, List_kind=23, Tuple_kind=24};
183+
Yield_kind=12, YieldFrom_kind=13, Compare_kind=14,
184+
Call_kind=15, Num_kind=16, Str_kind=17, Bytes_kind=18,
185+
Ellipsis_kind=19, Attribute_kind=20, Subscript_kind=21,
186+
Starred_kind=22, Name_kind=23, List_kind=24, Tuple_kind=25};
187187
struct _expr {
188188
enum _expr_kind kind;
189189
union {
@@ -245,10 +245,13 @@ struct _expr {
245245
} GeneratorExp;
246246

247247
struct {
248-
int is_from;
249248
expr_ty value;
250249
} Yield;
251250

251+
struct {
252+
expr_ty value;
253+
} YieldFrom;
254+
252255
struct {
253256
expr_ty left;
254257
asdl_int_seq *ops;
@@ -488,9 +491,11 @@ expr_ty _Py_DictComp(expr_ty key, expr_ty value, asdl_seq * generators, int
488491
#define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4)
489492
expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int
490493
col_offset, PyArena *arena);
491-
#define Yield(a0, a1, a2, a3, a4) _Py_Yield(a0, a1, a2, a3, a4)
492-
expr_ty _Py_Yield(int is_from, expr_ty value, int lineno, int col_offset,
493-
PyArena *arena);
494+
#define Yield(a0, a1, a2, a3) _Py_Yield(a0, a1, a2, a3)
495+
expr_ty _Py_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena);
496+
#define YieldFrom(a0, a1, a2, a3) _Py_YieldFrom(a0, a1, a2, a3)
497+
expr_ty _Py_YieldFrom(expr_ty value, int lineno, int col_offset, PyArena
498+
*arena);
494499
#define Compare(a0, a1, a2, a3, a4, a5) _Py_Compare(a0, a1, a2, a3, a4, a5)
495500
expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators,
496501
int lineno, int col_offset, PyArena *arena);

‎Lib/test/test_ast.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -813,8 +813,8 @@ def factory(comps):
813813
self._check_comprehension(factory)
814814

815815
def test_yield(self):
816-
self.expr(ast.Yield(0, ast.Name("x", ast.Store())), "must have Load")
817-
self.expr(ast.Yield(1, ast.Name("x", ast.Store())), "must have Load")
816+
self.expr(ast.Yield(ast.Name("x", ast.Store())), "must have Load")
817+
self.expr(ast.YieldFrom(ast.Name("x", ast.Store())), "must have Load")
818818

819819
def test_compare(self):
820820
left = ast.Name("x", ast.Load())

‎Parser/Python.asdl‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ module Python
5959
| DictComp(expr key, expr value, comprehension* generators)
6060
| GeneratorExp(expr elt, comprehension* generators)
6161
-- the grammar constrains where yield expressions can occur
62-
| Yield(int is_from, expr? value)
62+
| Yield(expr? value)
63+
| YieldFrom(expr? value)
6364
-- need sequences for compare to distinguish between
6465
-- x < 4 < 3 and (x < 4) < 3
6566
| Compare(expr left, cmpop* ops, expr* comparators)

‎Python/Python-ast.c‎

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,11 @@ static char *GeneratorExp_fields[]={
231231
"generators",
232232
};
233233
static PyTypeObject *Yield_type;
234-
_Py_IDENTIFIER(is_from);
235234
static char *Yield_fields[]={
236-
"is_from",
235+
"value",
236+
};
237+
static PyTypeObject *YieldFrom_type;
238+
static char *YieldFrom_fields[]={
237239
"value",
238240
};
239241
static PyTypeObject *Compare_type;
@@ -812,8 +814,10 @@ static int init_types(void)
812814
GeneratorExp_type = make_type("GeneratorExp", expr_type,
813815
GeneratorExp_fields, 2);
814816
if (!GeneratorExp_type) return 0;
815-
Yield_type = make_type("Yield", expr_type, Yield_fields, 2);
817+
Yield_type = make_type("Yield", expr_type, Yield_fields, 1);
816818
if (!Yield_type) return 0;
819+
YieldFrom_type = make_type("YieldFrom", expr_type, YieldFrom_fields, 1);
820+
if (!YieldFrom_type) return 0;
817821
Compare_type = make_type("Compare", expr_type, Compare_fields, 3);
818822
if (!Compare_type) return 0;
819823
Call_type = make_type("Call", expr_type, Call_fields, 5);
@@ -1749,20 +1753,33 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
17491753
}
17501754

17511755
expr_ty
1752-
Yield(int is_from, expr_ty value, int lineno, int col_offset, PyArena *arena)
1756+
Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
17531757
{
17541758
expr_ty p;
17551759
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
17561760
if (!p)
17571761
return NULL;
17581762
p->kind = Yield_kind;
1759-
p->v.Yield.is_from = is_from;
17601763
p->v.Yield.value = value;
17611764
p->lineno = lineno;
17621765
p->col_offset = col_offset;
17631766
return p;
17641767
}
17651768

1769+
expr_ty
1770+
YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
1771+
{
1772+
expr_ty p;
1773+
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
1774+
if (!p)
1775+
return NULL;
1776+
p->kind = YieldFrom_kind;
1777+
p->v.YieldFrom.value = value;
1778+
p->lineno = lineno;
1779+
p->col_offset = col_offset;
1780+
return p;
1781+
}
1782+
17661783
expr_ty
17671784
Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno,
17681785
int col_offset, PyArena *arena)
@@ -2798,12 +2815,16 @@ ast2obj_expr(void* _o)
27982815
case Yield_kind:
27992816
result = PyType_GenericNew(Yield_type, NULL, NULL);
28002817
if (!result) goto failed;
2801-
value = ast2obj_int(o->v.Yield.is_from);
2818+
value = ast2obj_expr(o->v.Yield.value);
28022819
if (!value) goto failed;
2803-
if (_PyObject_SetAttrId(result, &PyId_is_from, value) == -1)
2820+
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
28042821
goto failed;
28052822
Py_DECREF(value);
2806-
value = ast2obj_expr(o->v.Yield.value);
2823+
break;
2824+
case YieldFrom_kind:
2825+
result = PyType_GenericNew(YieldFrom_type, NULL, NULL);
2826+
if (!result) goto failed;
2827+
value = ast2obj_expr(o->v.YieldFrom.value);
28072828
if (!value) goto failed;
28082829
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
28092830
goto failed;
@@ -5345,21 +5366,30 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
53455366
return 1;
53465367
}
53475368
if (isinstance) {
5348-
int is_from;
53495369
expr_ty value;
53505370

5351-
if (_PyObject_HasAttrId(obj, &PyId_is_from)) {
5371+
if (_PyObject_HasAttrId(obj, &PyId_value)) {
53525372
int res;
5353-
tmp = _PyObject_GetAttrId(obj, &PyId_is_from);
5373+
tmp = _PyObject_GetAttrId(obj, &PyId_value);
53545374
if (tmp == NULL) goto failed;
5355-
res = obj2ast_int(tmp, &is_from, arena);
5375+
res = obj2ast_expr(tmp, &value, arena);
53565376
if (res != 0) goto failed;
53575377
Py_XDECREF(tmp);
53585378
tmp = NULL;
53595379
} else {
5360-
PyErr_SetString(PyExc_TypeError, "required field \"is_from\" missing from Yield");
5361-
return 1;
5380+
value = NULL;
53625381
}
5382+
*out = Yield(value, lineno, col_offset, arena);
5383+
if (*out == NULL) goto failed;
5384+
return 0;
5385+
}
5386+
isinstance = PyObject_IsInstance(obj, (PyObject*)YieldFrom_type);
5387+
if (isinstance == -1) {
5388+
return 1;
5389+
}
5390+
if (isinstance) {
5391+
expr_ty value;
5392+
53635393
if (_PyObject_HasAttrId(obj, &PyId_value)) {
53645394
int res;
53655395
tmp = _PyObject_GetAttrId(obj, &PyId_value);
@@ -5371,7 +5401,7 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
53715401
} else {
53725402
value = NULL;
53735403
}
5374-
*out = Yield(is_from, value, lineno, col_offset, arena);
5404+
*out = YieldFrom(value, lineno, col_offset, arena);
53755405
if (*out == NULL) goto failed;
53765406
return 0;
53775407
}
@@ -6928,6 +6958,8 @@ PyInit__ast(void)
69286958
(PyObject*)GeneratorExp_type) < 0) return NULL;
69296959
if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return
69306960
NULL;
6961+
if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) <
6962+
0) return NULL;
69316963
if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0)
69326964
return NULL;
69336965
if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return

‎Python/ast.c‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,9 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
223223
validate_expr(exp->v.DictComp.value, Load);
224224
case Yield_kind:
225225
return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
226+
case YieldFrom_kind:
227+
return !exp->v.YieldFrom.value ||
228+
validate_expr(exp->v.YieldFrom.value, Load);
226229
case Compare_kind:
227230
if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
228231
PyErr_SetString(PyExc_ValueError, "Compare with no comparators");
@@ -942,6 +945,7 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
942945
expr_name = "generator expression";
943946
break;
944947
case Yield_kind:
948+
case YieldFrom_kind:
945949
expr_name = "yield expression";
946950
break;
947951
case ListComp_kind:
@@ -2386,7 +2390,9 @@ ast_for_expr(struct compiling *c, const node *n)
23862390
if (!exp)
23872391
return NULL;
23882392
}
2389-
return Yield(is_from, exp, LINENO(n), n->n_col_offset, c->c_arena);
2393+
if (is_from)
2394+
return YieldFrom(exp, LINENO(n), n->n_col_offset, c->c_arena);
2395+
return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);
23902396
}
23912397
case factor:
23922398
if (NCH(n) == 1) {

‎Python/compile.c‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3311,21 +3311,25 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
33113311
case DictComp_kind:
33123312
return compiler_dictcomp(c, e);
33133313
case Yield_kind:
3314+
case YieldFrom_kind: {
3315+
expr_ty value;
33143316
if (c->u->u_ste->ste_type != FunctionBlock)
33153317
return compiler_error(c, "'yield' outside function");
3316-
if (e->v.Yield.value) {
3317-
VISIT(c, expr, e->v.Yield.value);
3318+
value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
3319+
if (value) {
3320+
VISIT(c, expr, value);
33183321
}
33193322
else {
33203323
ADDOP_O(c, LOAD_CONST, Py_None, consts);
33213324
}
3322-
if (e->v.Yield.is_from) {
3325+
if (e->kind == YieldFrom_kind) {
33233326
ADDOP(c, YIELD_FROM);
33243327
}
33253328
else {
33263329
ADDOP(c, YIELD_VALUE);
33273330
}
33283331
break;
3332+
}
33293333
case Compare_kind:
33303334
return compiler_compare(c, e);
33313335
case Call_kind:

‎Python/symtable.c‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1330,10 +1330,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
13301330
return 0;
13311331
break;
13321332
case Yield_kind:
1333-
if (e->v.Yield.value)
1334-
VISIT(st, expr, e->v.Yield.value);
1333+
case YieldFrom_kind: {
1334+
expr_ty value;
1335+
value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
1336+
if (value)
1337+
VISIT(st, expr, value);
13351338
st->st_cur->ste_generator = 1;
13361339
break;
1340+
}
13371341
case Compare_kind:
13381342
VISIT(st, expr, e->v.Compare.left);
13391343
VISIT_SEQ(st, expr, e->v.Compare.comparators);

0 commit comments

Comments
 (0)