diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 2f684d4183e519..d8628b81465df7 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -181,7 +181,7 @@ Include/internal/pycore_time.h @pganssle @abalkin
# AST
Python/ast.c @isidentical @JelleZijlstra @eclips4
-Python/ast_opt.c @isidentical @eclips4
+Python/ast_process.c @isidentical @eclips4
Parser/asdl.py @isidentical @JelleZijlstra @eclips4
Parser/asdl_c.py @isidentical @JelleZijlstra @eclips4
Lib/ast.py @isidentical @JelleZijlstra @eclips4
diff --git a/Include/internal/pycore_compile.h b/Include/internal/pycore_compile.h
index b98dfb0cebbd3f..8ac097ce068093 100644
--- a/Include/internal/pycore_compile.h
+++ b/Include/internal/pycore_compile.h
@@ -34,8 +34,8 @@ PyAPI_FUNC(PyCodeObject*) _PyAST_Compile(
int optimize,
struct _arena *arena);
-/* AST optimizations */
-extern int _PyCompile_AstOptimize(
+/* AST processing */
+extern int _PyCompile_AstProcess(
struct _mod *mod,
PyObject *filename,
PyCompilerFlags *flags,
@@ -43,7 +43,7 @@ extern int _PyCompile_AstOptimize(
struct _arena *arena,
int syntax_check_only);
-extern int _PyAST_Optimize(
+extern int _PyAST_Process(
struct _mod *,
struct _arena *arena,
PyObject *filename,
diff --git a/InternalDocs/compiler.md b/InternalDocs/compiler.md
index 8ca19a42b91b83..cb455cf02fc881 100644
--- a/InternalDocs/compiler.md
+++ b/InternalDocs/compiler.md
@@ -505,8 +505,8 @@ Important files
* [Python/ast.c](../Python/ast.c):
Used for validating the AST.
- * [Python/ast_opt.c](../Python/ast_opt.c):
- Optimizes the AST.
+ * [Python/ast_process.c](../Python/ast_process.c):
+ Processes the AST before compiling.
* [Python/ast_unparse.c](../Python/ast_unparse.c):
Converts the AST expression node back into a string (for string annotations).
diff --git a/Makefile.pre.in b/Makefile.pre.in
index 9658bfa44b98e4..15b511d2bd0196 100644
--- a/Makefile.pre.in
+++ b/Makefile.pre.in
@@ -426,7 +426,7 @@ PYTHON_OBJS= \
Python/asdl.o \
Python/assemble.o \
Python/ast.o \
- Python/ast_opt.o \
+ Python/ast_process.o \
Python/ast_unparse.o \
Python/bltinmodule.o \
Python/brc.o \
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-03-28-15-06-55.gh-issue-126835.IpcMTn.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-28-15-06-55.gh-issue-126835.IpcMTn.rst
new file mode 100644
index 00000000000000..9ed55660e9c712
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-03-28-15-06-55.gh-issue-126835.IpcMTn.rst
@@ -0,0 +1,3 @@
+Move constant folding to the peephole optimizer. Rename AST optimization
+related files (Python/ast_opt.c -> Python/ast_process.c), structs (_PyASTOptimizeState -> _PyASTProcessState)
+and functions (_PyAST_Optimize -> _PyAST_Process, _PyCompile_AstOptimize -> _PyCompile_AstProcess).
diff --git a/PCbuild/_freeze_module.vcxproj b/PCbuild/_freeze_module.vcxproj
index 44292ee32b19fa..62e8494f91e2c6 100644
--- a/PCbuild/_freeze_module.vcxproj
+++ b/PCbuild/_freeze_module.vcxproj
@@ -188,7 +188,7 @@
-
+
diff --git a/PCbuild/_freeze_module.vcxproj.filters b/PCbuild/_freeze_module.vcxproj.filters
index 3842f52e514bb4..6a8e6a67b936ae 100644
--- a/PCbuild/_freeze_module.vcxproj.filters
+++ b/PCbuild/_freeze_module.vcxproj.filters
@@ -34,7 +34,7 @@
Source Files
-
+
Source Files
diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj
index 2e639ddfc320f5..a54fac96c197a6 100644
--- a/PCbuild/pythoncore.vcxproj
+++ b/PCbuild/pythoncore.vcxproj
@@ -571,7 +571,7 @@
-
+
diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters
index 31064f50f5c8d7..0d5f53808f9ee7 100644
--- a/PCbuild/pythoncore.vcxproj.filters
+++ b/PCbuild/pythoncore.vcxproj.filters
@@ -1301,7 +1301,7 @@
Python
-
+
Python
diff --git a/Python/ast_opt.c b/Python/ast_process.c
similarity index 93%
rename from Python/ast_opt.c
rename to Python/ast_process.c
index 99a2418da46e35..e8d6b9fc369e65 100644
--- a/Python/ast_opt.c
+++ b/Python/ast_process.c
@@ -1,4 +1,3 @@
-/* AST Optimizer */
#include "Python.h"
#include "pycore_ast.h" // _PyAST_GetDocString()
#include "pycore_c_array.h" // _Py_CArray_EnsureCapacity()
@@ -23,7 +22,7 @@ typedef struct {
_Py_c_array_t cf_finally; /* context for PEP 678 check */
int cf_finally_used;
-} _PyASTOptimizeState;
+} _PyASTProcessState;
#define ENTER_RECURSIVE() \
if (Py_EnterRecursiveCall(" during compilation")) { \
@@ -33,14 +32,14 @@ if (Py_EnterRecursiveCall(" during compilation")) { \
#define LEAVE_RECURSIVE() Py_LeaveRecursiveCall();
static ControlFlowInFinallyContext*
-get_cf_finally_top(_PyASTOptimizeState *state)
+get_cf_finally_top(_PyASTProcessState *state)
{
int idx = state->cf_finally_used;
return ((ControlFlowInFinallyContext*)state->cf_finally.array) + idx;
}
static int
-push_cf_context(_PyASTOptimizeState *state, stmt_ty node, bool finally, bool funcdef, bool loop)
+push_cf_context(_PyASTProcessState *state, stmt_ty node, bool finally, bool funcdef, bool loop)
{
if (_Py_CArray_EnsureCapacity(&state->cf_finally, state->cf_finally_used+1) < 0) {
return 0;
@@ -56,14 +55,14 @@ push_cf_context(_PyASTOptimizeState *state, stmt_ty node, bool finally, bool fun
}
static void
-pop_cf_context(_PyASTOptimizeState *state)
+pop_cf_context(_PyASTProcessState *state)
{
assert(state->cf_finally_used > 0);
state->cf_finally_used--;
}
static int
-control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTOptimizeState *state)
+control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTProcessState *state)
{
PyObject *msg = PyUnicode_FromFormat("'%s' in a 'finally' block", kw);
if (msg == NULL) {
@@ -77,7 +76,7 @@ control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTOptimizeState *
}
static int
-before_return(_PyASTOptimizeState *state, stmt_ty node_)
+before_return(_PyASTProcessState *state, stmt_ty node_)
{
if (state->cf_finally_used > 0) {
ControlFlowInFinallyContext *ctx = get_cf_finally_top(state);
@@ -91,7 +90,7 @@ before_return(_PyASTOptimizeState *state, stmt_ty node_)
}
static int
-before_loop_exit(_PyASTOptimizeState *state, stmt_ty node_, const char *kw)
+before_loop_exit(_PyASTProcessState *state, stmt_ty node_, const char *kw)
{
if (state->cf_finally_used > 0) {
ControlFlowInFinallyContext *ctx = get_cf_finally_top(state);
@@ -366,7 +365,7 @@ optimize_format(expr_ty node, PyObject *fmt, asdl_expr_seq *elts, PyArena *arena
}
static int
-fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
+fold_binop(expr_ty node, PyArena *arena, _PyASTProcessState *state)
{
if (state->syntax_check_only) {
return 1;
@@ -390,18 +389,18 @@ fold_binop(expr_ty node, PyArena *arena, _PyASTOptimizeState *state)
return 1;
}
-static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
-static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state);
+static int astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTProcessState *state);
+static int astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTProcessState *state);
#define CALL(FUNC, TYPE, ARG) \
if (!FUNC((ARG), ctx_, state)) \
@@ -437,7 +436,7 @@ stmt_seq_remove_item(asdl_stmt_seq *stmts, Py_ssize_t idx)
}
static int
-astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTProcessState *state)
{
int docstring = _PyAST_GetDocString(stmts) != NULL;
if (docstring && (state->optimize >= 2)) {
@@ -467,7 +466,7 @@ astfold_body(asdl_stmt_seq *stmts, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
switch (node_->kind) {
case Module_kind:
@@ -489,7 +488,7 @@ astfold_mod(mod_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
ENTER_RECURSIVE();
switch (node_->kind) {
@@ -607,14 +606,14 @@ astfold_expr(expr_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_keyword(keyword_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
CALL(astfold_expr, expr_ty, node_->value);
return 1;
}
static int
-astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
CALL(astfold_expr, expr_ty, node_->target);
CALL(astfold_expr, expr_ty, node_->iter);
@@ -623,7 +622,7 @@ astfold_comprehension(comprehension_ty node_, PyArena *ctx_, _PyASTOptimizeState
}
static int
-astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
CALL_SEQ(astfold_arg, arg, node_->posonlyargs);
CALL_SEQ(astfold_arg, arg, node_->args);
@@ -636,7 +635,7 @@ astfold_arguments(arguments_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
CALL_OPT(astfold_expr, expr_ty, node_->annotation);
@@ -645,7 +644,7 @@ astfold_arg(arg_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
ENTER_RECURSIVE();
switch (node_->kind) {
@@ -800,7 +799,7 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
switch (node_->kind) {
case ExceptHandler_kind:
@@ -814,7 +813,7 @@ astfold_excepthandler(excepthandler_ty node_, PyArena *ctx_, _PyASTOptimizeState
}
static int
-astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
CALL(astfold_expr, expr_ty, node_->context_expr);
CALL_OPT(astfold_expr, expr_ty, node_->optional_vars);
@@ -822,7 +821,7 @@ astfold_withitem(withitem_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTOptimizeState *state)
+fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTProcessState *state)
{
if (state->syntax_check_only) {
return 1;
@@ -863,7 +862,7 @@ fold_const_match_patterns(expr_ty node, PyArena *ctx_, _PyASTOptimizeState *stat
}
static int
-astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
// Currently, this is really only used to form complex/negative numeric
// constants in MatchValue and MatchMapping nodes
@@ -905,7 +904,7 @@ astfold_pattern(pattern_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
}
static int
-astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
CALL(astfold_pattern, expr_ty, node_->pattern);
CALL_OPT(astfold_expr, expr_ty, node_->guard);
@@ -914,7 +913,7 @@ astfold_match_case(match_case_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat
}
static int
-astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
+astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTProcessState *state)
{
switch (node_->kind) {
case TypeVar_kind:
@@ -936,11 +935,11 @@ astfold_type_param(type_param_ty node_, PyArena *ctx_, _PyASTOptimizeState *stat
#undef CALL_SEQ
int
-_PyAST_Optimize(mod_ty mod, PyArena *arena, PyObject *filename, int optimize,
- int ff_features, int syntax_check_only)
+_PyAST_Process(mod_ty mod, PyArena *arena, PyObject *filename, int optimize,
+ int ff_features, int syntax_check_only)
{
- _PyASTOptimizeState state;
- memset(&state, 0, sizeof(_PyASTOptimizeState));
+ _PyASTProcessState state;
+ memset(&state, 0, sizeof(_PyASTProcessState));
state.filename = filename;
state.optimize = optimize;
state.ff_features = ff_features;
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index 10e415fa052f64..09a549aaae378a 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -847,7 +847,7 @@ builtin_compile_impl(PyObject *module, PyObject *source, PyObject *filename,
goto error;
}
int syntax_check_only = ((flags & PyCF_OPTIMIZED_AST) == PyCF_ONLY_AST); /* unoptiomized AST */
- if (_PyCompile_AstOptimize(mod, filename, &cf, optimize,
+ if (_PyCompile_AstProcess(mod, filename, &cf, optimize,
arena, syntax_check_only) < 0) {
_PyArena_Free(arena);
goto error;
diff --git a/Python/compile.c b/Python/compile.c
index 430898b5966842..0cb5564a08bdf1 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -134,7 +134,7 @@ compiler_setup(compiler *c, mod_ty mod, PyObject *filename,
c->c_optimize = (optimize == -1) ? _Py_GetConfig()->optimization_level : optimize;
c->c_save_nested_seqs = false;
- if (!_PyAST_Optimize(mod, arena, filename, c->c_optimize, merged, 0)) {
+ if (!_PyAST_Process(mod, arena, filename, c->c_optimize, merged, 0)) {
return ERROR;
}
c->c_st = _PySymtable_Build(mod, filename, &c->c_future);
@@ -1449,8 +1449,8 @@ _PyAST_Compile(mod_ty mod, PyObject *filename, PyCompilerFlags *pflags,
}
int
-_PyCompile_AstOptimize(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
- int optimize, PyArena *arena, int no_const_folding)
+_PyCompile_AstProcess(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
+ int optimize, PyArena *arena, int no_const_folding)
{
_PyFutureFeatures future;
if (!_PyFuture_FromAST(mod, filename, &future)) {
@@ -1460,7 +1460,7 @@ _PyCompile_AstOptimize(mod_ty mod, PyObject *filename, PyCompilerFlags *cf,
if (optimize == -1) {
optimize = _Py_GetConfig()->optimization_level;
}
- if (!_PyAST_Optimize(mod, arena, filename, optimize, flags, no_const_folding)) {
+ if (!_PyAST_Process(mod, arena, filename, optimize, flags, no_const_folding)) {
return -1;
}
return 0;
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 23af8b6f6be8e8..35260f5893d1d1 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -1498,7 +1498,7 @@ Py_CompileStringObject(const char *str, PyObject *filename, int start,
}
if (flags && (flags->cf_flags & PyCF_ONLY_AST)) {
int syntax_check_only = ((flags->cf_flags & PyCF_OPTIMIZED_AST) == PyCF_ONLY_AST); /* unoptiomized AST */
- if (_PyCompile_AstOptimize(mod, filename, flags, optimize, arena, syntax_check_only) < 0) {
+ if (_PyCompile_AstProcess(mod, filename, flags, optimize, arena, syntax_check_only) < 0) {
_PyArena_Free(arena);
return NULL;
}
diff --git a/Tools/c-analyzer/cpython/ignored.tsv b/Tools/c-analyzer/cpython/ignored.tsv
index 9b624d809879ff..dc0195bfaed64f 100644
--- a/Tools/c-analyzer/cpython/ignored.tsv
+++ b/Tools/c-analyzer/cpython/ignored.tsv
@@ -347,7 +347,6 @@ Objects/unicodeobject.c unicode_translate_call_errorhandler argparse -
Parser/parser.c - reserved_keywords -
Parser/parser.c - soft_keywords -
Parser/lexer/lexer.c - type_comment_prefix -
-Python/ast_opt.c fold_unaryop ops -
Python/ceval.c - _PyEval_BinaryOps -
Python/ceval.c - _Py_INTERPRETER_TRAMPOLINE_INSTRUCTIONS -
Python/codecs.c - Py_hexdigits -