[Python-checkins] cpython: make YieldFrom its own distinct from Yield (closes #13780)
benjamin.peterson
python-checkins at python.org
Sat Jan 14 14:58:28 CET 2012
http://hg.python.org/cpython/rev/e1177b9167ce
changeset: 74391:e1177b9167ce
user: Benjamin Peterson <benjamin at python.org>
date: Sat Jan 14 08:58:23 2012 -0500
summary:
make YieldFrom its own distinct from Yield (closes #13780)
files:
Include/Python-ast.h | 21 +++++---
Lib/test/test_ast.py | 4 +-
Parser/Python.asdl | 3 +-
Python/Python-ast.c | 76 ++++++++++++++++++++++---------
Python/ast.c | 8 ++-
Python/compile.c | 10 ++-
Python/symtable.c | 8 ++-
7 files changed, 91 insertions(+), 39 deletions(-)
diff --git a/Include/Python-ast.h b/Include/Python-ast.h
--- a/Include/Python-ast.h
+++ b/Include/Python-ast.h
@@ -180,10 +180,10 @@
enum _expr_kind {BoolOp_kind=1, BinOp_kind=2, UnaryOp_kind=3, Lambda_kind=4,
IfExp_kind=5, Dict_kind=6, Set_kind=7, ListComp_kind=8,
SetComp_kind=9, DictComp_kind=10, GeneratorExp_kind=11,
- Yield_kind=12, Compare_kind=13, Call_kind=14, Num_kind=15,
- Str_kind=16, Bytes_kind=17, Ellipsis_kind=18,
- Attribute_kind=19, Subscript_kind=20, Starred_kind=21,
- Name_kind=22, List_kind=23, Tuple_kind=24};
+ Yield_kind=12, YieldFrom_kind=13, Compare_kind=14,
+ Call_kind=15, Num_kind=16, Str_kind=17, Bytes_kind=18,
+ Ellipsis_kind=19, Attribute_kind=20, Subscript_kind=21,
+ Starred_kind=22, Name_kind=23, List_kind=24, Tuple_kind=25};
struct _expr {
enum _expr_kind kind;
union {
@@ -245,11 +245,14 @@
} GeneratorExp;
struct {
- int is_from;
expr_ty value;
} Yield;
struct {
+ expr_ty value;
+ } YieldFrom;
+
+ struct {
expr_ty left;
asdl_int_seq *ops;
asdl_seq *comparators;
@@ -488,9 +491,11 @@
#define GeneratorExp(a0, a1, a2, a3, a4) _Py_GeneratorExp(a0, a1, a2, a3, a4)
expr_ty _Py_GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int
col_offset, PyArena *arena);
-#define Yield(a0, a1, a2, a3, a4) _Py_Yield(a0, a1, a2, a3, a4)
-expr_ty _Py_Yield(int is_from, expr_ty value, int lineno, int col_offset,
- PyArena *arena);
+#define Yield(a0, a1, a2, a3) _Py_Yield(a0, a1, a2, a3)
+expr_ty _Py_Yield(expr_ty value, int lineno, int col_offset, PyArena *arena);
+#define YieldFrom(a0, a1, a2, a3) _Py_YieldFrom(a0, a1, a2, a3)
+expr_ty _Py_YieldFrom(expr_ty value, int lineno, int col_offset, PyArena
+ *arena);
#define Compare(a0, a1, a2, a3, a4, a5) _Py_Compare(a0, a1, a2, a3, a4, a5)
expr_ty _Py_Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators,
int lineno, int col_offset, PyArena *arena);
diff --git a/Lib/test/test_ast.py b/Lib/test/test_ast.py
--- a/Lib/test/test_ast.py
+++ b/Lib/test/test_ast.py
@@ -813,8 +813,8 @@
self._check_comprehension(factory)
def test_yield(self):
- self.expr(ast.Yield(0, ast.Name("x", ast.Store())), "must have Load")
- self.expr(ast.Yield(1, ast.Name("x", ast.Store())), "must have Load")
+ self.expr(ast.Yield(ast.Name("x", ast.Store())), "must have Load")
+ self.expr(ast.YieldFrom(ast.Name("x", ast.Store())), "must have Load")
def test_compare(self):
left = ast.Name("x", ast.Load())
diff --git a/Parser/Python.asdl b/Parser/Python.asdl
--- a/Parser/Python.asdl
+++ b/Parser/Python.asdl
@@ -59,7 +59,8 @@
| DictComp(expr key, expr value, comprehension* generators)
| GeneratorExp(expr elt, comprehension* generators)
-- the grammar constrains where yield expressions can occur
- | Yield(int is_from, expr? value)
+ | Yield(expr? value)
+ | YieldFrom(expr? value)
-- need sequences for compare to distinguish between
-- x < 4 < 3 and (x < 4) < 3
| Compare(expr left, cmpop* ops, expr* comparators)
diff --git a/Python/Python-ast.c b/Python/Python-ast.c
--- a/Python/Python-ast.c
+++ b/Python/Python-ast.c
@@ -231,9 +231,11 @@
"generators",
};
static PyTypeObject *Yield_type;
-_Py_IDENTIFIER(is_from);
static char *Yield_fields[]={
- "is_from",
+ "value",
+};
+static PyTypeObject *YieldFrom_type;
+static char *YieldFrom_fields[]={
"value",
};
static PyTypeObject *Compare_type;
@@ -812,8 +814,10 @@
GeneratorExp_type = make_type("GeneratorExp", expr_type,
GeneratorExp_fields, 2);
if (!GeneratorExp_type) return 0;
- Yield_type = make_type("Yield", expr_type, Yield_fields, 2);
+ 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);
+ if (!YieldFrom_type) return 0;
Compare_type = make_type("Compare", expr_type, Compare_fields, 3);
if (!Compare_type) return 0;
Call_type = make_type("Call", expr_type, Call_fields, 5);
@@ -1749,14 +1753,13 @@
}
expr_ty
-Yield(int is_from, expr_ty value, int lineno, int col_offset, PyArena *arena)
+Yield(expr_ty value, int lineno, int col_offset, PyArena *arena)
{
expr_ty p;
p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
if (!p)
return NULL;
p->kind = Yield_kind;
- p->v.Yield.is_from = is_from;
p->v.Yield.value = value;
p->lineno = lineno;
p->col_offset = col_offset;
@@ -1764,6 +1767,20 @@
}
expr_ty
+YieldFrom(expr_ty value, int lineno, int col_offset, PyArena *arena)
+{
+ expr_ty p;
+ p = (expr_ty)PyArena_Malloc(arena, sizeof(*p));
+ if (!p)
+ return NULL;
+ p->kind = YieldFrom_kind;
+ p->v.YieldFrom.value = value;
+ p->lineno = lineno;
+ p->col_offset = col_offset;
+ return p;
+}
+
+expr_ty
Compare(expr_ty left, asdl_int_seq * ops, asdl_seq * comparators, int lineno,
int col_offset, PyArena *arena)
{
@@ -2798,12 +2815,16 @@
case Yield_kind:
result = PyType_GenericNew(Yield_type, NULL, NULL);
if (!result) goto failed;
- value = ast2obj_int(o->v.Yield.is_from);
+ value = ast2obj_expr(o->v.Yield.value);
if (!value) goto failed;
- if (_PyObject_SetAttrId(result, &PyId_is_from, value) == -1)
+ if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
goto failed;
Py_DECREF(value);
- value = ast2obj_expr(o->v.Yield.value);
+ break;
+ case YieldFrom_kind:
+ result = PyType_GenericNew(YieldFrom_type, NULL, NULL);
+ if (!result) goto failed;
+ value = ast2obj_expr(o->v.YieldFrom.value);
if (!value) goto failed;
if (_PyObject_SetAttrId(result, &PyId_value, value) == -1)
goto failed;
@@ -5345,21 +5366,8 @@
return 1;
}
if (isinstance) {
- int is_from;
expr_ty value;
- if (_PyObject_HasAttrId(obj, &PyId_is_from)) {
- int res;
- tmp = _PyObject_GetAttrId(obj, &PyId_is_from);
- if (tmp == NULL) goto failed;
- res = obj2ast_int(tmp, &is_from, arena);
- if (res != 0) goto failed;
- Py_XDECREF(tmp);
- tmp = NULL;
- } else {
- PyErr_SetString(PyExc_TypeError, "required field \"is_from\" missing from Yield");
- return 1;
- }
if (_PyObject_HasAttrId(obj, &PyId_value)) {
int res;
tmp = _PyObject_GetAttrId(obj, &PyId_value);
@@ -5371,7 +5379,29 @@
} else {
value = NULL;
}
- *out = Yield(is_from, value, lineno, col_offset, arena);
+ *out = Yield(value, lineno, col_offset, arena);
+ if (*out == NULL) goto failed;
+ return 0;
+ }
+ isinstance = PyObject_IsInstance(obj, (PyObject*)YieldFrom_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_XDECREF(tmp);
+ tmp = NULL;
+ } else {
+ value = NULL;
+ }
+ *out = YieldFrom(value, lineno, col_offset, arena);
if (*out == NULL) goto failed;
return 0;
}
@@ -6928,6 +6958,8 @@
(PyObject*)GeneratorExp_type) < 0) return NULL;
if (PyDict_SetItemString(d, "Yield", (PyObject*)Yield_type) < 0) return
NULL;
+ if (PyDict_SetItemString(d, "YieldFrom", (PyObject*)YieldFrom_type) <
+ 0) return NULL;
if (PyDict_SetItemString(d, "Compare", (PyObject*)Compare_type) < 0)
return NULL;
if (PyDict_SetItemString(d, "Call", (PyObject*)Call_type) < 0) return
diff --git a/Python/ast.c b/Python/ast.c
--- a/Python/ast.c
+++ b/Python/ast.c
@@ -223,6 +223,9 @@
validate_expr(exp->v.DictComp.value, Load);
case Yield_kind:
return !exp->v.Yield.value || validate_expr(exp->v.Yield.value, Load);
+ case YieldFrom_kind:
+ return !exp->v.YieldFrom.value ||
+ validate_expr(exp->v.YieldFrom.value, Load);
case Compare_kind:
if (!asdl_seq_LEN(exp->v.Compare.comparators)) {
PyErr_SetString(PyExc_ValueError, "Compare with no comparators");
@@ -942,6 +945,7 @@
expr_name = "generator expression";
break;
case Yield_kind:
+ case YieldFrom_kind:
expr_name = "yield expression";
break;
case ListComp_kind:
@@ -2386,7 +2390,9 @@
if (!exp)
return NULL;
}
- return Yield(is_from, exp, LINENO(n), n->n_col_offset, c->c_arena);
+ if (is_from)
+ return YieldFrom(exp, LINENO(n), n->n_col_offset, c->c_arena);
+ return Yield(exp, LINENO(n), n->n_col_offset, c->c_arena);
}
case factor:
if (NCH(n) == 1) {
diff --git a/Python/compile.c b/Python/compile.c
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3311,21 +3311,25 @@
case DictComp_kind:
return compiler_dictcomp(c, e);
case Yield_kind:
+ case YieldFrom_kind: {
+ expr_ty value;
if (c->u->u_ste->ste_type != FunctionBlock)
return compiler_error(c, "'yield' outside function");
- if (e->v.Yield.value) {
- VISIT(c, expr, e->v.Yield.value);
+ value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
+ if (value) {
+ VISIT(c, expr, value);
}
else {
ADDOP_O(c, LOAD_CONST, Py_None, consts);
}
- if (e->v.Yield.is_from) {
+ if (e->kind == YieldFrom_kind) {
ADDOP(c, YIELD_FROM);
}
else {
ADDOP(c, YIELD_VALUE);
}
break;
+ }
case Compare_kind:
return compiler_compare(c, e);
case Call_kind:
diff --git a/Python/symtable.c b/Python/symtable.c
--- a/Python/symtable.c
+++ b/Python/symtable.c
@@ -1330,10 +1330,14 @@
return 0;
break;
case Yield_kind:
- if (e->v.Yield.value)
- VISIT(st, expr, e->v.Yield.value);
+ case YieldFrom_kind: {
+ expr_ty value;
+ value = (e->kind == YieldFrom_kind) ? e->v.YieldFrom.value : e->v.Yield.value;
+ if (value)
+ VISIT(st, expr, 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);
--
Repository URL: http://hg.python.org/cpython
More information about the Python-checkins
mailing list