summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuido van Rossum <guido@python.org>2023-02-08 01:35:55 (GMT)
committerGitHub <noreply@github.com>2023-02-08 01:35:55 (GMT)
commitb2b85b5db9cfdb24f966b61757536a898abc3830 (patch)
treeb5f09e352132a15f5e782e75ce6205b3da0552b1
parentaacbdb0c650492756738b044e6ddf8b72f89a1a2 (diff)
downloadcpython-b2b85b5db9cfdb24f966b61757536a898abc3830.zip
cpython-b2b85b5db9cfdb24f966b61757536a898abc3830.tar.gz
cpython-b2b85b5db9cfdb24f966b61757536a898abc3830.tar.bz2
gh-98831: Modernize FORMAT_VALUE (#101628)
Generator update: support balanced parentheses and brackets in conditions and size expressions.
-rw-r--r--Python/bytecodes.c18
-rw-r--r--Python/generated_cases.c.h20
-rw-r--r--Python/opcode_metadata.h4
-rw-r--r--Tools/cases_generator/parser.py9
-rw-r--r--Tools/cases_generator/test_generator.py8
5 files changed, 24 insertions, 35 deletions
diff --git a/Python/bytecodes.c b/Python/bytecodes.c
index c6c00a7..d0f0513 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 ded68d0..3ef8086 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 c1e12a4..52bab1c 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 ced66fa..c7c8d8a 100644
--- a/Tools/cases_generator/parser.py
+++ b/Tools/cases_generator/parser.py
@@ -263,7 +263,14 @@ class Parser(PLexer):
@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 0c3d04b..33bba7e 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); }