Skip to content

Commit ed2f4e7

Browse files
committed
use stack for context
1 parent df8f210 commit ed2f4e7

File tree

1 file changed

+57
-37
lines changed

1 file changed

+57
-37
lines changed

Python/ast_opt.c

Lines changed: 57 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include "pycore_long.h" // _PyLong
66
#include "pycore_pystate.h" // _PyThreadState_GET()
77
#include "pycore_setobject.h" // _PySet_NextEntry()
8+
#include "cpython/code.h" // CO_MAXBLOCKS
89

910

1011
/* See PEP 765 */
@@ -23,7 +24,8 @@ typedef struct {
2324
int recursion_depth; /* current recursion depth */
2425
int recursion_limit; /* recursion limit */
2526

26-
ControlFlowInFinallyContext cf_finally;
27+
int cf_finally_next;
28+
ControlFlowInFinallyContext cf_finally[CO_MAXBLOCKS];
2729
} _PyASTOptimizeState;
2830

2931
#define ENTER_RECURSIVE(ST) \
@@ -41,20 +43,27 @@ typedef struct {
4143
} while(0)
4244

4345

44-
static ControlFlowInFinallyContext
45-
overwrite_state(_PyASTOptimizeState *state, bool finally, bool funcdef, bool loop)
46+
static int
47+
push_cf_context(_PyASTOptimizeState *state, stmt_ty node, bool finally, bool funcdef, bool loop)
4648
{
47-
ControlFlowInFinallyContext saved = state->cf_finally;
48-
state->cf_finally.in_finally = finally;
49-
state->cf_finally.in_funcdef = funcdef;
50-
state->cf_finally.in_loop = loop;
51-
return saved;
49+
if (state->cf_finally_next == CO_MAXBLOCKS) {
50+
PyErr_SetString(PyExc_SyntaxError, "too many statically nested blocks");
51+
PyErr_RangedSyntaxLocationObject(state->filename, node->lineno, node->col_offset + 1,
52+
node->end_lineno, node->end_col_offset + 1);
53+
return 0;
54+
}
55+
ControlFlowInFinallyContext *ctx = &state->cf_finally[state->cf_finally_next++];
56+
ctx->in_finally = finally;
57+
ctx->in_funcdef = funcdef;
58+
ctx->in_loop = loop;
59+
return 1;
5260
}
5361

5462
static void
55-
restore_state(_PyASTOptimizeState *state, ControlFlowInFinallyContext *saved)
63+
pop_cf_context(_PyASTOptimizeState *state)
5664
{
57-
state->cf_finally = *saved;
65+
assert(state->cf_finally_next > 0);
66+
state->cf_finally_next--;
5867
}
5968

6069
static int
@@ -74,9 +83,12 @@ control_flow_in_finally_warning(const char *kw, stmt_ty n, _PyASTOptimizeState *
7483
static int
7584
before_return(_PyASTOptimizeState *state, stmt_ty node_)
7685
{
77-
if (state->cf_finally.in_finally && ! state->cf_finally.in_funcdef) {
78-
if (!control_flow_in_finally_warning("return", node_, state)) {
79-
return 0;
86+
if (state->cf_finally_next > 0) {
87+
ControlFlowInFinallyContext *ctx = &state->cf_finally[state->cf_finally_next - 1];
88+
if (ctx->in_finally && ! ctx->in_funcdef) {
89+
if (!control_flow_in_finally_warning("return", node_, state)) {
90+
return 0;
91+
}
8092
}
8193
}
8294
return 1;
@@ -85,22 +97,30 @@ before_return(_PyASTOptimizeState *state, stmt_ty node_)
8597
static int
8698
before_loop_exit(_PyASTOptimizeState *state, stmt_ty node_, const char *kw)
8799
{
88-
if (state->cf_finally.in_finally && ! state->cf_finally.in_loop) {
89-
if (!control_flow_in_finally_warning(kw, node_, state)) {
90-
return 0;
100+
if (state->cf_finally_next > 0) {
101+
ControlFlowInFinallyContext *ctx = &state->cf_finally[state->cf_finally_next - 1];
102+
if (ctx->in_finally && ! ctx->in_loop) {
103+
if (!control_flow_in_finally_warning(kw, node_, state)) {
104+
return 0;
105+
}
91106
}
92107
}
93108
return 1;
94109
}
95110

96-
#define RESTORE_STATE(S, CFS) restore_state((S), (CFS))
111+
#define PUSH_CONTEXT(S, N, FINALLY, FUNCDEF, LOOP) \
112+
if (!push_cf_context((S), (N), (FINALLY), (FUNCDEF), (LOOP))) { \
113+
return 0; \
114+
}
115+
116+
#define POP_CONTEXT(S) pop_cf_context(S)
97117

98-
#define BEFORE_FINALLY(S) overwrite_state((S), true, false, false)
99-
#define AFTER_FINALLY(S, CFS) RESTORE_STATE((S), (CFS))
100-
#define BEFORE_FUNC_BODY(S) overwrite_state((S), false, true, false)
101-
#define AFTER_FUNC_BODY(S, CFS) RESTORE_STATE((S), (CFS))
102-
#define BEFORE_LOOP_BODY(S) overwrite_state((S), false, false, true)
103-
#define AFTER_LOOP_BODY(S, CFS) RESTORE_STATE((S), (CFS))
118+
#define BEFORE_FINALLY(S, N) PUSH_CONTEXT((S), (N), true, false, false)
119+
#define AFTER_FINALLY(S) POP_CONTEXT(S)
120+
#define BEFORE_FUNC_BODY(S, N) PUSH_CONTEXT((S), (N), false, true, false)
121+
#define AFTER_FUNC_BODY(S) POP_CONTEXT(S)
122+
#define BEFORE_LOOP_BODY(S, N) PUSH_CONTEXT((S), (N), false, false, true)
123+
#define AFTER_LOOP_BODY(S) POP_CONTEXT(S)
104124

105125
#define BEFORE_RETURN(S, N) \
106126
if (!before_return((S), (N))) { \
@@ -923,9 +943,9 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
923943
case FunctionDef_kind: {
924944
CALL_SEQ(astfold_type_param, type_param, node_->v.FunctionDef.type_params);
925945
CALL(astfold_arguments, arguments_ty, node_->v.FunctionDef.args);
926-
ControlFlowInFinallyContext saved_context = BEFORE_FUNC_BODY(state);
946+
BEFORE_FUNC_BODY(state, node_);
927947
CALL(astfold_body, asdl_seq, node_->v.FunctionDef.body);
928-
AFTER_FUNC_BODY(state, &saved_context);
948+
AFTER_FUNC_BODY(state);
929949
CALL_SEQ(astfold_expr, expr, node_->v.FunctionDef.decorator_list);
930950
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
931951
CALL_OPT(astfold_expr, expr_ty, node_->v.FunctionDef.returns);
@@ -935,9 +955,9 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
935955
case AsyncFunctionDef_kind: {
936956
CALL_SEQ(astfold_type_param, type_param, node_->v.AsyncFunctionDef.type_params);
937957
CALL(astfold_arguments, arguments_ty, node_->v.AsyncFunctionDef.args);
938-
ControlFlowInFinallyContext saved_context = BEFORE_FUNC_BODY(state);
958+
BEFORE_FUNC_BODY(state, node_);
939959
CALL(astfold_body, asdl_seq, node_->v.AsyncFunctionDef.body);
940-
AFTER_FUNC_BODY(state, &saved_context);
960+
AFTER_FUNC_BODY(state);
941961
CALL_SEQ(astfold_expr, expr, node_->v.AsyncFunctionDef.decorator_list);
942962
if (!(state->ff_features & CO_FUTURE_ANNOTATIONS)) {
943963
CALL_OPT(astfold_expr, expr_ty, node_->v.AsyncFunctionDef.returns);
@@ -981,26 +1001,26 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
9811001
case For_kind: {
9821002
CALL(astfold_expr, expr_ty, node_->v.For.target);
9831003
CALL(astfold_expr, expr_ty, node_->v.For.iter);
984-
ControlFlowInFinallyContext saved_context = BEFORE_LOOP_BODY(state);
1004+
BEFORE_LOOP_BODY(state, node_);
9851005
CALL_SEQ(astfold_stmt, stmt, node_->v.For.body);
986-
AFTER_LOOP_BODY(state, &saved_context);
1006+
AFTER_LOOP_BODY(state);
9871007
CALL_SEQ(astfold_stmt, stmt, node_->v.For.orelse);
9881008
break;
9891009
}
9901010
case AsyncFor_kind: {
9911011
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.target);
9921012
CALL(astfold_expr, expr_ty, node_->v.AsyncFor.iter);
993-
ControlFlowInFinallyContext saved_context = BEFORE_LOOP_BODY(state);
1013+
BEFORE_LOOP_BODY(state, node_);
9941014
CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.body);
995-
AFTER_LOOP_BODY(state, &saved_context);
1015+
AFTER_LOOP_BODY(state);
9961016
CALL_SEQ(astfold_stmt, stmt, node_->v.AsyncFor.orelse);
9971017
break;
9981018
}
9991019
case While_kind: {
10001020
CALL(astfold_expr, expr_ty, node_->v.While.test);
1001-
ControlFlowInFinallyContext saved_context = BEFORE_LOOP_BODY(state);
1021+
BEFORE_LOOP_BODY(state, node_);
10021022
CALL_SEQ(astfold_stmt, stmt, node_->v.While.body);
1003-
AFTER_LOOP_BODY(state, &saved_context);
1023+
AFTER_LOOP_BODY(state);
10041024
CALL_SEQ(astfold_stmt, stmt, node_->v.While.orelse);
10051025
break;
10061026
}
@@ -1025,18 +1045,18 @@ astfold_stmt(stmt_ty node_, PyArena *ctx_, _PyASTOptimizeState *state)
10251045
CALL_SEQ(astfold_stmt, stmt, node_->v.Try.body);
10261046
CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.Try.handlers);
10271047
CALL_SEQ(astfold_stmt, stmt, node_->v.Try.orelse);
1028-
ControlFlowInFinallyContext saved_context = BEFORE_FINALLY(state);
1048+
BEFORE_FINALLY(state, node_);
10291049
CALL_SEQ(astfold_stmt, stmt, node_->v.Try.finalbody);
1030-
AFTER_FINALLY(state, &saved_context);
1050+
AFTER_FINALLY(state);
10311051
break;
10321052
}
10331053
case TryStar_kind: {
10341054
CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.body);
10351055
CALL_SEQ(astfold_excepthandler, excepthandler, node_->v.TryStar.handlers);
10361056
CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.orelse);
1037-
ControlFlowInFinallyContext saved_context = BEFORE_FINALLY(state);
1057+
BEFORE_FINALLY(state, node_);
10381058
CALL_SEQ(astfold_stmt, stmt, node_->v.TryStar.finalbody);
1039-
AFTER_FINALLY(state, &saved_context);
1059+
AFTER_FINALLY(state);
10401060
break;
10411061
}
10421062
case Assert_kind:

0 commit comments

Comments
 (0)