GH-77273: Better bytecodes for f-strings (GH-6132)

This commit is contained in:
Mark Shannon 2023-06-14 16:15:08 +01:00 committed by GitHub
parent 307bceaa65
commit 1d857da7f0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 525 additions and 485 deletions

View file

@ -52,6 +52,8 @@
#define family(name, ...) static int family_##name
#define pseudo(name) static int pseudo_##name
typedef PyObject *(*convertion_func_ptr)(PyObject *);
// Dummy variables for stack effects.
static PyObject *value, *value1, *value2, *left, *right, *res, *sum, *prod, *sub;
static PyObject *container, *start, *stop, *v, *lhs, *rhs, *res2;
@ -3367,43 +3369,35 @@ dummy_func(
ERROR_IF(slice == NULL, error);
}
inst(FORMAT_VALUE, (value, fmt_spec if ((oparg & FVS_MASK) == FVS_HAVE_SPEC) -- result)) {
/* Handles f-string value formatting. */
PyObject *(*conv_fn)(PyObject *);
int which_conversion = oparg & FVC_MASK;
/* See if any conversion is specified. */
switch (which_conversion) {
case FVC_NONE: conv_fn = NULL; break;
case FVC_STR: conv_fn = PyObject_Str; break;
case FVC_REPR: conv_fn = PyObject_Repr; break;
case FVC_ASCII: conv_fn = PyObject_ASCII; break;
default:
_PyErr_Format(tstate, PyExc_SystemError,
"unexpected conversion flag %d",
which_conversion);
goto error;
}
/* If there's a conversion function, call it and replace
value with that result. Otherwise, just use value,
without conversion. */
if (conv_fn != NULL) {
result = conv_fn(value);
Py_DECREF(value);
if (result == NULL) {
Py_XDECREF(fmt_spec);
ERROR_IF(true, error);
}
value = result;
}
result = PyObject_Format(value, fmt_spec);
inst(CONVERT_VALUE, (value -- result)) {
convertion_func_ptr conv_fn;
assert(oparg >= FVC_STR && oparg <= FVC_ASCII);
conv_fn = CONVERSION_FUNCTIONS[oparg];
result = conv_fn(value);
Py_DECREF(value);
Py_XDECREF(fmt_spec);
ERROR_IF(result == NULL, error);
}
inst(FORMAT_SIMPLE, (value -- res)) {
/* If value is a unicode object, then we know the result
* of format(value) is value itself. */
if (!PyUnicode_CheckExact(value)) {
res = PyObject_Format(value, NULL);
Py_DECREF(value);
ERROR_IF(res == NULL, error);
}
else {
res = value;
}
}
inst(FORMAT_WITH_SPEC, (value, fmt_spec -- res)) {
res = PyObject_Format(value, fmt_spec);
Py_DECREF(value);
Py_DECREF(fmt_spec);
ERROR_IF(res == NULL, error);
}
inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {
assert(oparg > 0);
top = Py_NewRef(bottom);