[Python-checkins] gh-98831: Modernize FORMAT_VALUE (#101628)

gvanrossum webhook-mailer at python.org
Tue Feb 7 20:36:02 EST 2023


https://github.com/python/cpython/commit/b2b85b5db9cfdb24f966b61757536a898abc3830
commit: b2b85b5db9cfdb24f966b61757536a898abc3830
branch: main
author: Guido van Rossum <guido at python.org>
committer: gvanrossum <gvanrossum at gmail.com>
date: 2023-02-07T17:35:55-08:00
summary:

gh-98831: Modernize FORMAT_VALUE (#101628)

Generator update: support balanced parentheses and brackets in conditions and size expressions.

files:
M Python/bytecodes.c
M Python/generated_cases.c.h
M Python/opcode_metadata.h
M Tools/cases_generator/parser.py
M Tools/cases_generator/test_generator.py

diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c6c00a7ab9b0..d0f0513a36f8 100644
--- a/Python/bytecodes.c
+++ b/Python/bytecodes.c
@@ -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) {
@@ -3088,7 +3080,7 @@ dummy_func(
                 Py_DECREF(value);
                 if (result == NULL) {
                     Py_XDECREF(fmt_spec);
-                    goto error;
+                    ERROR_IF(true, error);
                 }
                 value = result;
             }
@@ -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)) {
diff --git a/Python/generated_cases.c.h b/Python/generated_cases.c.h
index ded68d011c6b..3ef808691e01 100644
--- a/Python/generated_cases.c.h
+++ b/Python/generated_cases.c.h
@@ -3703,16 +3703,12 @@
         }
 
         TARGET(FORMAT_VALUE) {
-            /* Handles f-string value formatting. */
+            PyObject *fmt_spec = ((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? PEEK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)) : NULL;
+            PyObject *value = PEEK(1 + (((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));
             PyObject *result;
-            PyObject *fmt_spec;
-            PyObject *value;
+            /* Handles f-string value formatting. */
             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) {
@@ -3735,7 +3731,7 @@
                 Py_DECREF(value);
                 if (result == NULL) {
                     Py_XDECREF(fmt_spec);
-                    goto error;
+                    if (true) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }
                 }
                 value = result;
             }
@@ -3753,12 +3749,10 @@
                 result = PyObject_Format(value, fmt_spec);
                 Py_DECREF(value);
                 Py_XDECREF(fmt_spec);
-                if (result == NULL) {
-                    goto error;
-                }
+                if (result == NULL) { STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0)); goto pop_1_error; }
             }
-
-            PUSH(result);
+            STACK_SHRINK((((oparg & FVS_MASK) == FVS_HAVE_SPEC) ? 1 : 0));
+            POKE(1, result);
             DISPATCH();
         }
 
diff --git a/Python/opcode_metadata.h b/Python/opcode_metadata.h
index c1e12a4bbede..52bab1c680e3 100644
--- a/Python/opcode_metadata.h
+++ b/Python/opcode_metadata.h
@@ -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:
@@ -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:
diff --git a/Tools/cases_generator/parser.py b/Tools/cases_generator/parser.py
index ced66faee493..c7c8d8af6b73 100644
--- a/Tools/cases_generator/parser.py
+++ b/Tools/cases_generator/parser.py
@@ -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:
diff --git a/Tools/cases_generator/test_generator.py b/Tools/cases_generator/test_generator.py
index 0c3d04b45dd9..33bba7ee340a 100644
--- a/Tools/cases_generator/test_generator.py
+++ b/Tools/cases_generator/test_generator.py
@@ -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); }



More information about the Python-checkins mailing list