mirror of
https://github.com/python/cpython.git
synced 2025-08-30 13:38:43 +00:00
GH-98831: Implement array support in cases generator (#100912)
You can now write things like this: ``` inst(BUILD_STRING, (pieces[oparg] -- str)) { ... } inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) { ... } ``` Note that array output effects are only partially supported (they must be named `unused` or correspond to an input effect).
This commit is contained in:
parent
f34176b77f
commit
80e3e3423c
6 changed files with 398 additions and 177 deletions
|
@ -451,16 +451,12 @@ dummy_func(
|
|||
DISPATCH_INLINED(new_frame);
|
||||
}
|
||||
|
||||
// Alternative: (list, unused[oparg], v -- list, unused[oparg])
|
||||
inst(LIST_APPEND, (v --)) {
|
||||
PyObject *list = PEEK(oparg + 1); // +1 to account for v staying on stack
|
||||
inst(LIST_APPEND, (list, unused[oparg-1], v -- list, unused[oparg-1])) {
|
||||
ERROR_IF(_PyList_AppendTakeRef((PyListObject *)list, v) < 0, error);
|
||||
PREDICT(JUMP_BACKWARD);
|
||||
}
|
||||
|
||||
// Alternative: (set, unused[oparg], v -- set, unused[oparg])
|
||||
inst(SET_ADD, (v --)) {
|
||||
PyObject *set = PEEK(oparg + 1); // +1 to account for v staying on stack
|
||||
inst(SET_ADD, (set, unused[oparg-1], v -- set, unused[oparg-1])) {
|
||||
int err = PySet_Add(set, v);
|
||||
Py_DECREF(v);
|
||||
ERROR_IF(err, error);
|
||||
|
@ -532,7 +528,7 @@ dummy_func(
|
|||
ERROR_IF(res == NULL, error);
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- )
|
||||
// This should remain a legacy instruction.
|
||||
inst(RAISE_VARARGS) {
|
||||
PyObject *cause = NULL, *exc = NULL;
|
||||
switch (oparg) {
|
||||
|
@ -1295,40 +1291,25 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- __0)
|
||||
inst(BUILD_STRING) {
|
||||
PyObject *str;
|
||||
str = _PyUnicode_JoinArray(&_Py_STR(empty),
|
||||
stack_pointer - oparg, oparg);
|
||||
if (str == NULL)
|
||||
goto error;
|
||||
while (--oparg >= 0) {
|
||||
PyObject *item = POP();
|
||||
Py_DECREF(item);
|
||||
inst(BUILD_STRING, (pieces[oparg] -- str)) {
|
||||
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(pieces[i]);
|
||||
}
|
||||
PUSH(str);
|
||||
ERROR_IF(str == NULL, error);
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- __0)
|
||||
inst(BUILD_TUPLE) {
|
||||
STACK_SHRINK(oparg);
|
||||
PyObject *tup = _PyTuple_FromArraySteal(stack_pointer, oparg);
|
||||
if (tup == NULL)
|
||||
goto error;
|
||||
PUSH(tup);
|
||||
inst(BUILD_TUPLE, (values[oparg] -- tup)) {
|
||||
tup = _PyTuple_FromArraySteal(values, oparg);
|
||||
ERROR_IF(tup == NULL, error);
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- __0)
|
||||
inst(BUILD_LIST) {
|
||||
STACK_SHRINK(oparg);
|
||||
PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
|
||||
if (list == NULL)
|
||||
goto error;
|
||||
PUSH(list);
|
||||
inst(BUILD_LIST, (values[oparg] -- list)) {
|
||||
list = _PyList_FromArraySteal(values, oparg);
|
||||
ERROR_IF(list == NULL, error);
|
||||
}
|
||||
|
||||
inst(LIST_EXTEND, (iterable -- )) {
|
||||
PyObject *list = PEEK(oparg + 1); // iterable is still on the stack
|
||||
inst(LIST_EXTEND, (list, unused[oparg-1], iterable -- list, unused[oparg-1])) {
|
||||
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
|
||||
if (none_val == NULL) {
|
||||
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
|
||||
|
@ -1346,48 +1327,40 @@ dummy_func(
|
|||
DECREF_INPUTS();
|
||||
}
|
||||
|
||||
inst(SET_UPDATE, (iterable --)) {
|
||||
PyObject *set = PEEK(oparg + 1); // iterable is still on the stack
|
||||
inst(SET_UPDATE, (set, unused[oparg-1], iterable -- set, unused[oparg-1])) {
|
||||
int err = _PySet_Update(set, iterable);
|
||||
DECREF_INPUTS();
|
||||
ERROR_IF(err < 0, error);
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- __0)
|
||||
inst(BUILD_SET) {
|
||||
PyObject *set = PySet_New(NULL);
|
||||
inst(BUILD_SET, (values[oparg] -- set)) {
|
||||
set = PySet_New(NULL);
|
||||
int err = 0;
|
||||
int i;
|
||||
if (set == NULL)
|
||||
goto error;
|
||||
for (i = oparg; i > 0; i--) {
|
||||
PyObject *item = PEEK(i);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
PyObject *item = values[i];
|
||||
if (err == 0)
|
||||
err = PySet_Add(set, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
STACK_SHRINK(oparg);
|
||||
if (err != 0) {
|
||||
Py_DECREF(set);
|
||||
goto error;
|
||||
ERROR_IF(true, error);
|
||||
}
|
||||
PUSH(set);
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg*2] -- __0)
|
||||
inst(BUILD_MAP) {
|
||||
PyObject *map = _PyDict_FromItems(
|
||||
&PEEK(2*oparg), 2,
|
||||
&PEEK(2*oparg - 1), 2,
|
||||
inst(BUILD_MAP, (values[oparg*2] -- map)) {
|
||||
map = _PyDict_FromItems(
|
||||
values, 2,
|
||||
values+1, 2,
|
||||
oparg);
|
||||
if (map == NULL)
|
||||
goto error;
|
||||
|
||||
while (oparg--) {
|
||||
Py_DECREF(POP());
|
||||
Py_DECREF(POP());
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(values[i*2]);
|
||||
Py_DECREF(values[i*2+1]);
|
||||
}
|
||||
PUSH(map);
|
||||
ERROR_IF(map == NULL, error);
|
||||
}
|
||||
|
||||
inst(SETUP_ANNOTATIONS, (--)) {
|
||||
|
@ -1432,28 +1405,21 @@ dummy_func(
|
|||
}
|
||||
}
|
||||
|
||||
// stack effect: (__array[oparg] -- )
|
||||
inst(BUILD_CONST_KEY_MAP) {
|
||||
PyObject *map;
|
||||
PyObject *keys = TOP();
|
||||
inst(BUILD_CONST_KEY_MAP, (values[oparg], keys -- map)) {
|
||||
if (!PyTuple_CheckExact(keys) ||
|
||||
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
|
||||
_PyErr_SetString(tstate, PyExc_SystemError,
|
||||
"bad BUILD_CONST_KEY_MAP keys argument");
|
||||
goto error;
|
||||
goto error; // Pop the keys and values.
|
||||
}
|
||||
map = _PyDict_FromItems(
|
||||
&PyTuple_GET_ITEM(keys, 0), 1,
|
||||
&PEEK(oparg + 1), 1, oparg);
|
||||
if (map == NULL) {
|
||||
goto error;
|
||||
values, 1, oparg);
|
||||
Py_DECREF(keys);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(values[i]);
|
||||
}
|
||||
|
||||
Py_DECREF(POP());
|
||||
while (oparg--) {
|
||||
Py_DECREF(POP());
|
||||
}
|
||||
PUSH(map);
|
||||
ERROR_IF(map == NULL, error);
|
||||
}
|
||||
|
||||
inst(DICT_UPDATE, (update --)) {
|
||||
|
|
102
Python/generated_cases.c.h
generated
102
Python/generated_cases.c.h
generated
|
@ -574,7 +574,7 @@
|
|||
|
||||
TARGET(LIST_APPEND) {
|
||||
PyObject *v = PEEK(1);
|
||||
PyObject *list = PEEK(oparg + 1); // +1 to account for v staying on stack
|
||||
PyObject *list = PEEK(2 + (oparg-1));
|
||||
if (_PyList_AppendTakeRef((PyListObject *)list, v) < 0) goto pop_1_error;
|
||||
STACK_SHRINK(1);
|
||||
PREDICT(JUMP_BACKWARD);
|
||||
|
@ -583,7 +583,7 @@
|
|||
|
||||
TARGET(SET_ADD) {
|
||||
PyObject *v = PEEK(1);
|
||||
PyObject *set = PEEK(oparg + 1); // +1 to account for v staying on stack
|
||||
PyObject *set = PEEK(2 + (oparg-1));
|
||||
int err = PySet_Add(set, v);
|
||||
Py_DECREF(v);
|
||||
if (err) goto pop_1_error;
|
||||
|
@ -1511,40 +1511,44 @@
|
|||
}
|
||||
|
||||
TARGET(BUILD_STRING) {
|
||||
PyObject **pieces = &PEEK(oparg);
|
||||
PyObject *str;
|
||||
str = _PyUnicode_JoinArray(&_Py_STR(empty),
|
||||
stack_pointer - oparg, oparg);
|
||||
if (str == NULL)
|
||||
goto error;
|
||||
while (--oparg >= 0) {
|
||||
PyObject *item = POP();
|
||||
Py_DECREF(item);
|
||||
str = _PyUnicode_JoinArray(&_Py_STR(empty), pieces, oparg);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(pieces[i]);
|
||||
}
|
||||
PUSH(str);
|
||||
if (str == NULL) { STACK_SHRINK(oparg); goto error; }
|
||||
STACK_SHRINK(oparg);
|
||||
STACK_GROW(1);
|
||||
POKE(1, str);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BUILD_TUPLE) {
|
||||
PyObject **values = &PEEK(oparg);
|
||||
PyObject *tup;
|
||||
tup = _PyTuple_FromArraySteal(values, oparg);
|
||||
if (tup == NULL) { STACK_SHRINK(oparg); goto error; }
|
||||
STACK_SHRINK(oparg);
|
||||
PyObject *tup = _PyTuple_FromArraySteal(stack_pointer, oparg);
|
||||
if (tup == NULL)
|
||||
goto error;
|
||||
PUSH(tup);
|
||||
STACK_GROW(1);
|
||||
POKE(1, tup);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BUILD_LIST) {
|
||||
PyObject **values = &PEEK(oparg);
|
||||
PyObject *list;
|
||||
list = _PyList_FromArraySteal(values, oparg);
|
||||
if (list == NULL) { STACK_SHRINK(oparg); goto error; }
|
||||
STACK_SHRINK(oparg);
|
||||
PyObject *list = _PyList_FromArraySteal(stack_pointer, oparg);
|
||||
if (list == NULL)
|
||||
goto error;
|
||||
PUSH(list);
|
||||
STACK_GROW(1);
|
||||
POKE(1, list);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(LIST_EXTEND) {
|
||||
PyObject *iterable = PEEK(1);
|
||||
PyObject *list = PEEK(oparg + 1); // iterable is still on the stack
|
||||
PyObject *list = PEEK(2 + (oparg-1));
|
||||
PyObject *none_val = _PyList_Extend((PyListObject *)list, iterable);
|
||||
if (none_val == NULL) {
|
||||
if (_PyErr_ExceptionMatches(tstate, PyExc_TypeError) &&
|
||||
|
@ -1566,7 +1570,7 @@
|
|||
|
||||
TARGET(SET_UPDATE) {
|
||||
PyObject *iterable = PEEK(1);
|
||||
PyObject *set = PEEK(oparg + 1); // iterable is still on the stack
|
||||
PyObject *set = PEEK(2 + (oparg-1));
|
||||
int err = _PySet_Update(set, iterable);
|
||||
Py_DECREF(iterable);
|
||||
if (err < 0) goto pop_1_error;
|
||||
|
@ -1575,39 +1579,44 @@
|
|||
}
|
||||
|
||||
TARGET(BUILD_SET) {
|
||||
PyObject *set = PySet_New(NULL);
|
||||
PyObject **values = &PEEK(oparg);
|
||||
PyObject *set;
|
||||
set = PySet_New(NULL);
|
||||
int err = 0;
|
||||
int i;
|
||||
if (set == NULL)
|
||||
goto error;
|
||||
for (i = oparg; i > 0; i--) {
|
||||
PyObject *item = PEEK(i);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
PyObject *item = values[i];
|
||||
if (err == 0)
|
||||
err = PySet_Add(set, item);
|
||||
Py_DECREF(item);
|
||||
}
|
||||
STACK_SHRINK(oparg);
|
||||
if (err != 0) {
|
||||
Py_DECREF(set);
|
||||
goto error;
|
||||
if (true) { STACK_SHRINK(oparg); goto error; }
|
||||
}
|
||||
PUSH(set);
|
||||
STACK_SHRINK(oparg);
|
||||
STACK_GROW(1);
|
||||
POKE(1, set);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
TARGET(BUILD_MAP) {
|
||||
PyObject *map = _PyDict_FromItems(
|
||||
&PEEK(2*oparg), 2,
|
||||
&PEEK(2*oparg - 1), 2,
|
||||
PyObject **values = &PEEK(oparg*2);
|
||||
PyObject *map;
|
||||
map = _PyDict_FromItems(
|
||||
values, 2,
|
||||
values+1, 2,
|
||||
oparg);
|
||||
if (map == NULL)
|
||||
goto error;
|
||||
|
||||
while (oparg--) {
|
||||
Py_DECREF(POP());
|
||||
Py_DECREF(POP());
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(values[i*2]);
|
||||
Py_DECREF(values[i*2+1]);
|
||||
}
|
||||
PUSH(map);
|
||||
if (map == NULL) { STACK_SHRINK(oparg*2); goto error; }
|
||||
STACK_SHRINK(oparg*2);
|
||||
STACK_GROW(1);
|
||||
POKE(1, map);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
@ -1655,26 +1664,25 @@
|
|||
}
|
||||
|
||||
TARGET(BUILD_CONST_KEY_MAP) {
|
||||
PyObject *keys = PEEK(1);
|
||||
PyObject **values = &PEEK(1 + oparg);
|
||||
PyObject *map;
|
||||
PyObject *keys = TOP();
|
||||
if (!PyTuple_CheckExact(keys) ||
|
||||
PyTuple_GET_SIZE(keys) != (Py_ssize_t)oparg) {
|
||||
_PyErr_SetString(tstate, PyExc_SystemError,
|
||||
"bad BUILD_CONST_KEY_MAP keys argument");
|
||||
goto error;
|
||||
goto error; // Pop the keys and values.
|
||||
}
|
||||
map = _PyDict_FromItems(
|
||||
&PyTuple_GET_ITEM(keys, 0), 1,
|
||||
&PEEK(oparg + 1), 1, oparg);
|
||||
if (map == NULL) {
|
||||
goto error;
|
||||
values, 1, oparg);
|
||||
Py_DECREF(keys);
|
||||
for (int i = 0; i < oparg; i++) {
|
||||
Py_DECREF(values[i]);
|
||||
}
|
||||
|
||||
Py_DECREF(POP());
|
||||
while (oparg--) {
|
||||
Py_DECREF(POP());
|
||||
}
|
||||
PUSH(map);
|
||||
if (map == NULL) { STACK_SHRINK(oparg); goto pop_1_error; }
|
||||
STACK_SHRINK(oparg);
|
||||
POKE(1, map);
|
||||
DISPATCH();
|
||||
}
|
||||
|
||||
|
|
|
@ -45,8 +45,8 @@ static const struct {
|
|||
[BINARY_SUBSCR_TUPLE_INT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
|
||||
[BINARY_SUBSCR_DICT] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
|
||||
[BINARY_SUBSCR_GETITEM] = { 2, 1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC000 },
|
||||
[LIST_APPEND] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[SET_ADD] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[LIST_APPEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[SET_ADD] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[STORE_SUBSCR] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
|
||||
[STORE_SUBSCR_LIST_INT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
|
||||
[STORE_SUBSCR_DICT] = { 3, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IXC },
|
||||
|
@ -92,8 +92,8 @@ static const struct {
|
|||
[BUILD_STRING] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[BUILD_TUPLE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[BUILD_LIST] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[LIST_EXTEND] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[SET_UPDATE] = { 1, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[LIST_EXTEND] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[SET_UPDATE] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[BUILD_SET] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[BUILD_MAP] = { -1, -1, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IB },
|
||||
[SETUP_ANNOTATIONS] = { 0, 0, DIR_NONE, DIR_NONE, DIR_NONE, true, INSTR_FMT_IX },
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue