mirror of
https://github.com/python/cpython.git
synced 2025-10-21 14:12:27 +00:00
bpo-34822: Simplify AST for subscription. (GH-9605)
* Remove the slice type. * Make Slice a kind of the expr type instead of the slice type. * Replace ExtSlice(slices) with Tuple(slices, Load()). * Replace Index(value) with a value itself. All non-terminal nodes in AST for expressions are now of the expr type.
This commit is contained in:
parent
e5e56328af
commit
13d52c2686
15 changed files with 300 additions and 709 deletions
210
Python/compile.c
210
Python/compile.c
|
@ -193,8 +193,8 @@ static int compiler_visit_keyword(struct compiler *, keyword_ty);
|
|||
static int compiler_visit_expr(struct compiler *, expr_ty);
|
||||
static int compiler_augassign(struct compiler *, stmt_ty);
|
||||
static int compiler_annassign(struct compiler *, stmt_ty);
|
||||
static int compiler_visit_slice(struct compiler *, slice_ty,
|
||||
expr_context_ty);
|
||||
static int compiler_subscript(struct compiler *, expr_ty);
|
||||
static int compiler_slice(struct compiler *, expr_ty);
|
||||
|
||||
static int inplace_binop(struct compiler *, operator_ty);
|
||||
static int are_all_items_const(asdl_seq *, Py_ssize_t, Py_ssize_t);
|
||||
|
@ -4045,14 +4045,11 @@ check_subscripter(struct compiler *c, expr_ty e)
|
|||
}
|
||||
|
||||
static int
|
||||
check_index(struct compiler *c, expr_ty e, slice_ty s)
|
||||
check_index(struct compiler *c, expr_ty e, expr_ty s)
|
||||
{
|
||||
PyObject *v;
|
||||
|
||||
if (s->kind != Index_kind) {
|
||||
return 1;
|
||||
}
|
||||
PyTypeObject *index_type = infer_type(s->v.Index.value);
|
||||
PyTypeObject *index_type = infer_type(s);
|
||||
if (index_type == NULL
|
||||
|| PyType_FastSubclass(index_type, Py_TPFLAGS_LONG_SUBCLASS)
|
||||
|| index_type == &PySlice_Type) {
|
||||
|
@ -5065,39 +5062,7 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
}
|
||||
break;
|
||||
case Subscript_kind:
|
||||
switch (e->v.Subscript.ctx) {
|
||||
case AugLoad:
|
||||
VISIT(c, expr, e->v.Subscript.value);
|
||||
VISIT_SLICE(c, e->v.Subscript.slice, AugLoad);
|
||||
break;
|
||||
case Load:
|
||||
if (!check_subscripter(c, e->v.Subscript.value)) {
|
||||
return 0;
|
||||
}
|
||||
if (!check_index(c, e->v.Subscript.value, e->v.Subscript.slice)) {
|
||||
return 0;
|
||||
}
|
||||
VISIT(c, expr, e->v.Subscript.value);
|
||||
VISIT_SLICE(c, e->v.Subscript.slice, Load);
|
||||
break;
|
||||
case AugStore:
|
||||
VISIT_SLICE(c, e->v.Subscript.slice, AugStore);
|
||||
break;
|
||||
case Store:
|
||||
VISIT(c, expr, e->v.Subscript.value);
|
||||
VISIT_SLICE(c, e->v.Subscript.slice, Store);
|
||||
break;
|
||||
case Del:
|
||||
VISIT(c, expr, e->v.Subscript.value);
|
||||
VISIT_SLICE(c, e->v.Subscript.slice, Del);
|
||||
break;
|
||||
case Param:
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"param invalid in subscript expression");
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
return compiler_subscript(c, e);
|
||||
case Starred_kind:
|
||||
switch (e->v.Starred.ctx) {
|
||||
case Store:
|
||||
|
@ -5109,6 +5074,9 @@ compiler_visit_expr1(struct compiler *c, expr_ty e)
|
|||
return compiler_error(c,
|
||||
"can't use starred expression here");
|
||||
}
|
||||
break;
|
||||
case Slice_kind:
|
||||
return compiler_slice(c, e);
|
||||
case Name_kind:
|
||||
return compiler_nameop(c, e->v.Name.id, e->v.Name.ctx);
|
||||
/* child nodes of List and Tuple will have expr_context set */
|
||||
|
@ -5213,68 +5181,35 @@ check_annotation(struct compiler *c, stmt_ty s)
|
|||
}
|
||||
|
||||
static int
|
||||
check_ann_slice(struct compiler *c, slice_ty sl)
|
||||
{
|
||||
switch(sl->kind) {
|
||||
case Index_kind:
|
||||
return check_ann_expr(c, sl->v.Index.value);
|
||||
case Slice_kind:
|
||||
if (sl->v.Slice.lower && !check_ann_expr(c, sl->v.Slice.lower)) {
|
||||
return 0;
|
||||
}
|
||||
if (sl->v.Slice.upper && !check_ann_expr(c, sl->v.Slice.upper)) {
|
||||
return 0;
|
||||
}
|
||||
if (sl->v.Slice.step && !check_ann_expr(c, sl->v.Slice.step)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"unexpected slice kind");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
check_ann_subscr(struct compiler *c, slice_ty sl)
|
||||
check_ann_subscr(struct compiler *c, expr_ty e)
|
||||
{
|
||||
/* We check that everything in a subscript is defined at runtime. */
|
||||
Py_ssize_t i, n;
|
||||
|
||||
switch (sl->kind) {
|
||||
case Index_kind:
|
||||
switch (e->kind) {
|
||||
case Slice_kind:
|
||||
if (!check_ann_slice(c, sl)) {
|
||||
if (e->v.Slice.lower && !check_ann_expr(c, e->v.Slice.lower)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ExtSlice_kind:
|
||||
n = asdl_seq_LEN(sl->v.ExtSlice.dims);
|
||||
if (e->v.Slice.upper && !check_ann_expr(c, e->v.Slice.upper)) {
|
||||
return 0;
|
||||
}
|
||||
if (e->v.Slice.step && !check_ann_expr(c, e->v.Slice.step)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
case Tuple_kind: {
|
||||
/* extended slice */
|
||||
asdl_seq *elts = e->v.Tuple.elts;
|
||||
Py_ssize_t i, n = asdl_seq_LEN(elts);
|
||||
for (i = 0; i < n; i++) {
|
||||
slice_ty subsl = (slice_ty)asdl_seq_GET(sl->v.ExtSlice.dims, i);
|
||||
switch (subsl->kind) {
|
||||
case Index_kind:
|
||||
case Slice_kind:
|
||||
if (!check_ann_slice(c, subsl)) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ExtSlice_kind:
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"extended slice invalid in nested slice");
|
||||
if (!check_ann_subscr(c, asdl_seq_GET(elts, i))) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"invalid subscript kind %d", sl->kind);
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
default:
|
||||
return check_ann_expr(c, e);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -5400,12 +5335,20 @@ compiler_warn(struct compiler *c, const char *format, ...)
|
|||
}
|
||||
|
||||
static int
|
||||
compiler_handle_subscr(struct compiler *c, const char *kind,
|
||||
expr_context_ty ctx)
|
||||
compiler_subscript(struct compiler *c, expr_ty e)
|
||||
{
|
||||
expr_context_ty ctx = e->v.Subscript.ctx;
|
||||
int op = 0;
|
||||
|
||||
/* XXX this code is duplicated */
|
||||
if (ctx == Load) {
|
||||
if (!check_subscripter(c, e->v.Subscript.value)) {
|
||||
return 0;
|
||||
}
|
||||
if (!check_index(c, e->v.Subscript.value, e->v.Subscript.slice)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ctx) {
|
||||
case AugLoad: /* fall through to Load */
|
||||
case Load: op = BINARY_SUBSCR; break;
|
||||
|
@ -5413,23 +5356,26 @@ compiler_handle_subscr(struct compiler *c, const char *kind,
|
|||
case Store: op = STORE_SUBSCR; break;
|
||||
case Del: op = DELETE_SUBSCR; break;
|
||||
case Param:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"invalid %s kind %d in subscript\n",
|
||||
kind, ctx);
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"param invalid in subscript expression");
|
||||
return 0;
|
||||
}
|
||||
if (ctx == AugLoad) {
|
||||
ADDOP(c, DUP_TOP_TWO);
|
||||
}
|
||||
else if (ctx == AugStore) {
|
||||
if (ctx == AugStore) {
|
||||
ADDOP(c, ROT_THREE);
|
||||
}
|
||||
else {
|
||||
VISIT(c, expr, e->v.Subscript.value);
|
||||
VISIT(c, expr, e->v.Subscript.slice);
|
||||
if (ctx == AugLoad) {
|
||||
ADDOP(c, DUP_TOP_TWO);
|
||||
}
|
||||
}
|
||||
ADDOP(c, op);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
|
||||
compiler_slice(struct compiler *c, expr_ty s)
|
||||
{
|
||||
int n = 2;
|
||||
assert(s->kind == Slice_kind);
|
||||
|
@ -5457,64 +5403,6 @@ compiler_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_nested_slice(struct compiler *c, slice_ty s,
|
||||
expr_context_ty ctx)
|
||||
{
|
||||
switch (s->kind) {
|
||||
case Slice_kind:
|
||||
return compiler_slice(c, s, ctx);
|
||||
case Index_kind:
|
||||
VISIT(c, expr, s->v.Index.value);
|
||||
break;
|
||||
case ExtSlice_kind:
|
||||
default:
|
||||
PyErr_SetString(PyExc_SystemError,
|
||||
"extended slice invalid in nested slice");
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
compiler_visit_slice(struct compiler *c, slice_ty s, expr_context_ty ctx)
|
||||
{
|
||||
const char * kindname = NULL;
|
||||
switch (s->kind) {
|
||||
case Index_kind:
|
||||
kindname = "index";
|
||||
if (ctx != AugStore) {
|
||||
VISIT(c, expr, s->v.Index.value);
|
||||
}
|
||||
break;
|
||||
case Slice_kind:
|
||||
kindname = "slice";
|
||||
if (ctx != AugStore) {
|
||||
if (!compiler_slice(c, s, ctx))
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case ExtSlice_kind:
|
||||
kindname = "extended slice";
|
||||
if (ctx != AugStore) {
|
||||
Py_ssize_t i, n = asdl_seq_LEN(s->v.ExtSlice.dims);
|
||||
for (i = 0; i < n; i++) {
|
||||
slice_ty sub = (slice_ty)asdl_seq_GET(
|
||||
s->v.ExtSlice.dims, i);
|
||||
if (!compiler_visit_nested_slice(c, sub, ctx))
|
||||
return 0;
|
||||
}
|
||||
ADDOP_I(c, BUILD_TUPLE, n);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
PyErr_Format(PyExc_SystemError,
|
||||
"invalid subscript kind %d", s->kind);
|
||||
return 0;
|
||||
}
|
||||
return compiler_handle_subscr(c, kindname, ctx);
|
||||
}
|
||||
|
||||
/* End of the compiler section, beginning of the assembler section */
|
||||
|
||||
/* do depth-first search of basic block graph, starting with block.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue