Skip to content

Commit b2b85b5

Browse files
authored
gh-98831: Modernize FORMAT_VALUE (#101628)
Generator update: support balanced parentheses and brackets in conditions and size expressions.
1 parent aacbdb0 commit b2b85b5

File tree

5 files changed

+24
-35
lines changed

5 files changed

+24
-35
lines changed

Python/bytecodes.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3054,18 +3054,10 @@ dummy_func(
30543054
ERROR_IF(slice == NULL, error);
30553055
}
30563056

3057-
// error: FORMAT_VALUE has irregular stack effect
3058-
inst(FORMAT_VALUE) {
3057+
inst(FORMAT_VALUE, (value, fmt_spec if ((oparg & FVS_MASK) == FVS_HAVE_SPEC) -- result)) {
30593058
/* Handles f-string value formatting. */
3060-
PyObject *result;
3061-
PyObject *fmt_spec;
3062-
PyObject *value;
30633059
PyObject *(*conv_fn)(PyObject *);
30643060
int which_conversion = oparg & FVC_MASK;
3065-
int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC;
3066-
3067-
fmt_spec = have_fmt_spec ? POP() : NULL;
3068-
value = POP();
30693061

30703062
/* See if any conversion is specified. */
30713063
switch (which_conversion) {
@@ -3088,7 +3080,7 @@ dummy_func(
30883080
Py_DECREF(value);
30893081
if (result == NULL) {
30903082
Py_XDECREF(fmt_spec);
3091-
goto error;
3083+
ERROR_IF(true, error);
30923084
}
30933085
value = result;
30943086
}
@@ -3106,12 +3098,8 @@ dummy_func(
31063098
result = PyObject_Format(value, fmt_spec);
31073099
Py_DECREF(value);
31083100
Py_XDECREF(fmt_spec);
3109-
if (result == NULL) {
3110-
goto error;
3111-
}
3101+
ERROR_IF(result == NULL, error);
31123102
}
3113-
3114-
PUSH(result);
31153103
}
31163104

31173105
inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {

Python/generated_cases.c.h

Lines changed: 7 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Python/opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
333333
case BUILD_SLICE:
334334
return ((oparg == 3) ? 1 : 0) + 2;
335335
case FORMAT_VALUE:
336-
return -1;
336+
return (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0) + 1;
337337
case COPY:
338338
return (oparg-1) + 1;
339339
case BINARY_OP:
@@ -681,7 +681,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
681681
case BUILD_SLICE:
682682
return 1;
683683
case FORMAT_VALUE:
684-
return -1;
684+
return 1;
685685
case COPY:
686686
return (oparg-1) + 2;
687687
case BINARY_OP:

Tools/cases_generator/parser.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,14 @@ def stack_effect(self) -> StackEffect | None:
263263
@contextual
264264
def expression(self) -> Expression | None:
265265
tokens: list[lx.Token] = []
266-
while (tkn := self.peek()) and tkn.kind not in (lx.RBRACKET, lx.RPAREN):
266+
level = 1
267+
while tkn := self.peek():
268+
if tkn.kind in (lx.LBRACKET, lx.LPAREN):
269+
level += 1
270+
elif tkn.kind in (lx.RBRACKET, lx.RPAREN):
271+
level -= 1
272+
if level == 0:
273+
break
267274
tokens.append(tkn)
268275
self.next()
269276
if not tokens:

Tools/cases_generator/test_generator.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,20 +500,20 @@ def test_register():
500500

501501
def test_cond_effect():
502502
input = """
503-
inst(OP, (aa, input if (oparg & 1), cc -- xx, output if (oparg & 2), zz)) {
503+
inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
504504
output = spam(oparg, input);
505505
}
506506
"""
507507
output = """
508508
TARGET(OP) {
509509
PyObject *cc = PEEK(1);
510-
PyObject *input = (oparg & 1) ? PEEK(1 + ((oparg & 1) ? 1 : 0)) : NULL;
511-
PyObject *aa = PEEK(2 + ((oparg & 1) ? 1 : 0));
510+
PyObject *input = ((oparg & 1) == 1) ? PEEK(1 + (((oparg & 1) == 1) ? 1 : 0)) : NULL;
511+
PyObject *aa = PEEK(2 + (((oparg & 1) == 1) ? 1 : 0));
512512
PyObject *xx;
513513
PyObject *output = NULL;
514514
PyObject *zz;
515515
output = spam(oparg, input);
516-
STACK_SHRINK(((oparg & 1) ? 1 : 0));
516+
STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));
517517
STACK_GROW(((oparg & 2) ? 1 : 0));
518518
POKE(1, zz);
519519
if (oparg & 2) { POKE(1 + ((oparg & 2) ? 1 : 0), output); }

0 commit comments

Comments
 (0)