11/* AST Optimizer */
22#include "Python.h"
33#include "pycore_ast.h" // _PyAST_GetDocString()
4+ #include "pycore_c_array.h" // _Py_CArray_EnsureCapacity()
45#include "pycore_format.h" // F_LJUST
56#include "pycore_long.h" // _PyLong
67#include "pycore_pystate.h" // _PyThreadState_GET()
78#include "pycore_setobject.h" // _PySet_NextEntry()
8- #include "cpython/code.h" // CO_MAXBLOCKS
99
1010
1111/* See PEP 765 */
@@ -24,8 +24,8 @@ typedef struct {
2424 int recursion_depth ; /* current recursion depth */
2525 int recursion_limit ; /* recursion limit */
2626
27- int cf_finally_next ;
28- ControlFlowInFinallyContext cf_finally [ CO_MAXBLOCKS ] ;
27+ _Py_c_array_t cf_finally ; /* context for PEP 678 check */
28+ int cf_finally_used ;
2929} _PyASTOptimizeState ;
3030
3131#define ENTER_RECURSIVE () \
@@ -35,17 +35,23 @@ if (Py_EnterRecursiveCall(" during compilation")) { \
3535
3636#define LEAVE_RECURSIVE () Py_LeaveRecursiveCall();
3737
38+ static ControlFlowInFinallyContext *
39+ get_cf_finally_top (_PyASTOptimizeState * state )
40+ {
41+ int idx = state -> cf_finally_used + 1 ;
42+ return state -> cf_finally .array + idx * sizeof (ControlFlowInFinallyContext );
43+ }
3844
3945static int
4046push_cf_context (_PyASTOptimizeState * state , stmt_ty node , bool finally , bool funcdef , bool loop )
4147{
42- if (state -> cf_finally_next == CO_MAXBLOCKS ) {
43- PyErr_SetString (PyExc_SyntaxError , "too many statically nested blocks" );
44- PyErr_RangedSyntaxLocationObject (state -> filename , node -> lineno , node -> col_offset + 1 ,
45- node -> end_lineno , node -> end_col_offset + 1 );
48+ if (_Py_CArray_EnsureCapacity (& state -> cf_finally , state -> cf_finally_used + 1 ) < 0 ) {
4649 return 0 ;
4750 }
48- ControlFlowInFinallyContext * ctx = & state -> cf_finally [state -> cf_finally_next ++ ];
51+
52+ state -> cf_finally_used ++ ;
53+ ControlFlowInFinallyContext * ctx = get_cf_finally_top (state );
54+
4955 ctx -> in_finally = finally ;
5056 ctx -> in_funcdef = funcdef ;
5157 ctx -> in_loop = loop ;
@@ -55,8 +61,8 @@ push_cf_context(_PyASTOptimizeState *state, stmt_ty node, bool finally, bool fun
5561static void
5662pop_cf_context (_PyASTOptimizeState * state )
5763{
58- assert (state -> cf_finally_next > 0 );
59- state -> cf_finally_next -- ;
64+ assert (state -> cf_finally_used > 0 );
65+ state -> cf_finally_used -- ;
6066}
6167
6268static int
@@ -76,8 +82,8 @@ control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTOptimizeState *
7682static int
7783before_return (_PyASTOptimizeState * state , stmt_ty node_ )
7884{
79- if (state -> cf_finally_next > 0 ) {
80- ControlFlowInFinallyContext * ctx = & state -> cf_finally [ state -> cf_finally_next - 1 ] ;
85+ if (state -> cf_finally_used > 0 ) {
86+ ControlFlowInFinallyContext * ctx = get_cf_finally_top ( state ) ;
8187 if (ctx -> in_finally && ! ctx -> in_funcdef ) {
8288 if (!control_flow_in_finally_warning ("return" , node_ , state )) {
8389 return 0 ;
@@ -90,8 +96,8 @@ before_return(_PyASTOptimizeState *state, stmt_ty node_)
9096static int
9197before_loop_exit (_PyASTOptimizeState * state , stmt_ty node_ , const char * kw )
9298{
93- if (state -> cf_finally_next > 0 ) {
94- ControlFlowInFinallyContext * ctx = & state -> cf_finally [ state -> cf_finally_next - 1 ] ;
99+ if (state -> cf_finally_used > 0 ) {
100+ ControlFlowInFinallyContext * ctx = get_cf_finally_top ( state ) ;
95101 if (ctx -> in_finally && ! ctx -> in_loop ) {
96102 if (!control_flow_in_finally_warning (kw , node_ , state )) {
97103 return 0 ;
@@ -978,9 +984,13 @@ _PyAST_Optimize(mod_ty mod, PyArena *arena, PyObject *filename, int optimize,
978984 state .optimize = optimize ;
979985 state .ff_features = ff_features ;
980986 state .syntax_check_only = syntax_check_only ;
987+ if (_Py_CArray_Init (& state .cf_finally , sizeof (ControlFlowInFinallyContext ), 20 ) < 0 ) {
988+ return -1 ;
989+ }
981990
982991 int ret = astfold_mod (mod , arena , & state );
983992 assert (ret || PyErr_Occurred ());
984993
994+ _Py_CArray_Fini (& state .cf_finally );
985995 return ret ;
986996}
0 commit comments