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 -