make YieldFrom its own distinct from Yield (closes #13780)

This commit is contained in:
Benjamin Peterson 2012-01-14 08:58:23 -05:00
parent 91f252b179
commit 527c622926
7 changed files with 91 additions and 39 deletions

View file

@ -231,9 +231,11 @@ static char *GeneratorExp_fields[]={
"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 @@ static int init_types(void)
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,20 +1753,33 @@ GeneratorExp(expr_ty elt, asdl_seq * generators, int lineno, int col_offset,
}
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;
return p;
}
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 @@ ast2obj_expr(void* _o)
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 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
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 @@ obj2ast_expr(PyObject* obj, expr_ty* out, PyArena* arena)
} 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 @@ PyInit__ast(void)
(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

View file

@ -223,6 +223,9 @@ validate_expr(expr_ty exp, expr_context_ty ctx)
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 @@ set_context(struct compiling *c, expr_ty e, expr_context_ty ctx, const node *n)
expr_name = "generator expression";
break;
case Yield_kind:
case YieldFrom_kind:
expr_name = "yield expression";
break;
case ListComp_kind:
@ -2386,7 +2390,9 @@ ast_for_expr(struct compiling *c, const node *n)
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) {

View file

@ -3311,21 +3311,25 @@ compiler_visit_expr(struct compiler *c, expr_ty e)
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:

View file

@ -1330,10 +1330,14 @@ symtable_visit_expr(struct symtable *st, expr_ty e)
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);