diff --git a/Lib/test/test_compile.py b/Lib/test/test_compile.py index 566ca27fca893da..eedf6775143db67 100644 --- a/Lib/test/test_compile.py +++ b/Lib/test/test_compile.py @@ -648,6 +648,17 @@ def unused_code_at_end(): 'RETURN_VALUE', list(dis.get_instructions(unused_code_at_end))[-1].opname) + @support.cpython_only + def test_slice_folding(self): + def g(): + "abcde"[2:4] + gc = g.__code__.co_consts + + self.assertIn("cd", gc) + self.assertNotIn("abcde", gc) + self.assertNotIn(2, gc) + self.assertNotIn(4, gc) + def test_dont_merge_constants(self): # Issue #25843: compile() must not merge constants which are equal # but have a different type. diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-05-18-52-56.bpo-39223.caMNwy.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-05-18-52-56.bpo-39223.caMNwy.rst new file mode 100644 index 000000000000000..43148c79a62580f --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2020-01-05-18-52-56.bpo-39223.caMNwy.rst @@ -0,0 +1,2 @@ +Support slices (e.g: ``"abcde"[2:4]``) in constant folding. Patch by +Batuhan Taskaya. diff --git a/Python/ast_opt.c b/Python/ast_opt.c index 96c766fc0957d49..507f812acfb7281 100644 --- a/Python/ast_opt.c +++ b/Python/ast_opt.c @@ -305,26 +305,46 @@ fold_tuple(expr_ty node, PyArena *arena, int optimize) return make_const(node, newval, arena); } +#define ENSURE_CONSTANT(NODE) \ + if ((NODE) != NULL && (NODE)->kind != Constant_kind) \ + return 1; + +#define GET_CONSTANT(NODE) (((NODE) != NULL) ? (NODE)->v.Constant.value : NULL) + static int fold_subscr(expr_ty node, PyArena *arena, int optimize) { - PyObject *newval; - expr_ty arg, idx; + PyObject *newval, *key; + expr_ty arg; slice_ty slice; arg = node->v.Subscript.value; slice = node->v.Subscript.slice; - if (node->v.Subscript.ctx != Load || - arg->kind != Constant_kind || - /* TODO: handle other types of slices */ - slice->kind != Index_kind || - slice->v.Index.value->kind != Constant_kind) + if (node->v.Subscript.ctx != Load) { return 1; } + ENSURE_CONSTANT(arg); + switch (slice->kind) { + case Index_kind: + ENSURE_CONSTANT(slice->v.Index.value); + key = GET_CONSTANT(slice->v.Index.value); + newval = PyObject_GetItem(GET_CONSTANT(arg), key); + break; + case Slice_kind: + ENSURE_CONSTANT(slice->v.Slice.lower); + ENSURE_CONSTANT(slice->v.Slice.upper); + ENSURE_CONSTANT(slice->v.Slice.step); + key = PySlice_New(GET_CONSTANT(slice->v.Slice.lower), + GET_CONSTANT(slice->v.Slice.upper), + GET_CONSTANT(slice->v.Slice.step)); + newval = PyObject_GetItem(GET_CONSTANT(arg), key); + Py_DECREF(key); + break; + default: + return 1; + } - idx = slice->v.Index.value; - newval = PyObject_GetItem(arg->v.Constant.value, idx->v.Constant.value); return make_const(node, newval, arena); }