Skip to content

Commit

Permalink
gh-98831: Modernize FORMAT_VALUE (#101628)
Browse files Browse the repository at this point in the history
Generator update: support balanced parentheses and brackets in conditions and size expressions.
  • Loading branch information
gvanrossum authored Feb 8, 2023
1 parent aacbdb0 commit b2b85b5
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 35 deletions.
18 changes: 3 additions & 15 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3054,18 +3054,10 @@ dummy_func(
ERROR_IF(slice == NULL, error);
}

// error: FORMAT_VALUE has irregular stack effect
inst(FORMAT_VALUE) {
inst(FORMAT_VALUE, (value, fmt_spec if ((oparg & FVS_MASK) == FVS_HAVE_SPEC) -- result)) {
/* Handles f-string value formatting. */
PyObject *result;
PyObject *fmt_spec;
PyObject *value;
PyObject *(*conv_fn)(PyObject *);
int which_conversion = oparg & FVC_MASK;
int have_fmt_spec = (oparg & FVS_MASK) == FVS_HAVE_SPEC;

fmt_spec = have_fmt_spec ? POP() : NULL;
value = POP();

/* See if any conversion is specified. */
switch (which_conversion) {
Expand All @@ -3088,7 +3080,7 @@ dummy_func(
Py_DECREF(value);
if (result == NULL) {
Py_XDECREF(fmt_spec);
goto error;
ERROR_IF(true, error);
}
value = result;
}
Expand All @@ -3106,12 +3098,8 @@ dummy_func(
result = PyObject_Format(value, fmt_spec);
Py_DECREF(value);
Py_XDECREF(fmt_spec);
if (result == NULL) {
goto error;
}
ERROR_IF(result == NULL, error);
}

PUSH(result);
}

inst(COPY, (bottom, unused[oparg-1] -- bottom, unused[oparg-1], top)) {
Expand Down
20 changes: 7 additions & 13 deletions Python/generated_cases.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Python/opcode_metadata.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,7 @@ _PyOpcode_num_popped(int opcode, int oparg, bool jump) {
case BUILD_SLICE:
return ((oparg == 3) ? 1 : 0) + 2;
case FORMAT_VALUE:
return -1;
return (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0) + 1;
case COPY:
return (oparg-1) + 1;
case BINARY_OP:
Expand Down Expand Up @@ -681,7 +681,7 @@ _PyOpcode_num_pushed(int opcode, int oparg, bool jump) {
case BUILD_SLICE:
return 1;
case FORMAT_VALUE:
return -1;
return 1;
case COPY:
return (oparg-1) + 2;
case BINARY_OP:
Expand Down
9 changes: 8 additions & 1 deletion Tools/cases_generator/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,14 @@ def stack_effect(self) -> StackEffect | None:
@contextual
def expression(self) -> Expression | None:
tokens: list[lx.Token] = []
while (tkn := self.peek()) and tkn.kind not in (lx.RBRACKET, lx.RPAREN):
level = 1
while tkn := self.peek():
if tkn.kind in (lx.LBRACKET, lx.LPAREN):
level += 1
elif tkn.kind in (lx.RBRACKET, lx.RPAREN):
level -= 1
if level == 0:
break
tokens.append(tkn)
self.next()
if not tokens:
Expand Down
8 changes: 4 additions & 4 deletions Tools/cases_generator/test_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,20 +500,20 @@ def test_register():

def test_cond_effect():
input = """
inst(OP, (aa, input if (oparg & 1), cc -- xx, output if (oparg & 2), zz)) {
inst(OP, (aa, input if ((oparg & 1) == 1), cc -- xx, output if (oparg & 2), zz)) {
output = spam(oparg, input);
}
"""
output = """
TARGET(OP) {
PyObject *cc = PEEK(1);
PyObject *input = (oparg & 1) ? PEEK(1 + ((oparg & 1) ? 1 : 0)) : NULL;
PyObject *aa = PEEK(2 + ((oparg & 1) ? 1 : 0));
PyObject *input = ((oparg & 1) == 1) ? PEEK(1 + (((oparg & 1) == 1) ? 1 : 0)) : NULL;
PyObject *aa = PEEK(2 + (((oparg & 1) == 1) ? 1 : 0));
PyObject *xx;
PyObject *output = NULL;
PyObject *zz;
output = spam(oparg, input);
STACK_SHRINK(((oparg & 1) ? 1 : 0));
STACK_SHRINK((((oparg & 1) == 1) ? 1 : 0));
STACK_GROW(((oparg & 2) ? 1 : 0));
POKE(1, zz);
if (oparg & 2) { POKE(1 + ((oparg & 2) ? 1 : 0), output); }
Expand Down

0 comments on commit b2b85b5

Please sign in to comment.