[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v3] pkl: trans: get rid of pkl_ast_finish_breaks
From: |
Mohammad-Reza Nabipoor |
Subject: |
[PATCH v3] pkl: trans: get rid of pkl_ast_finish_breaks |
Date: |
Mon, 18 Jul 2022 01:30:40 +0430 |
2022-07-17 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* libpoke/pkl-ast.h (pkl_ast_finish_breaks): Remove.
* libpoke/pkl-ast.c (pkl_ast_finish_breaks): Likewise.
(pkl_ast_finish_breaks_1): Likewise.
* libpoke/pkl-tab.y (stmt): Likewise.
* libpoke/pkl-trans.h (struct pkl_trans_escapable_ctx): New struct.
(PKL_TRANS_MAX_COMP_STMT_NEST): New macro.
(struct pkl_trans_payload): Add new fields.
* libpoke/pkl-trans.c (PKL_TRANS_ESCAPABLE): New macro.
(PKL_TRANS_PUSH_ESCAPABLE): Likewise.
(PKL_TRANS_POP_ESCAPABLE): Likewise.
(pkl_trans1_pr_comp_stmt): Add logic to track lexical frames around
`break` and `continue` keywords.
(pkl_trans1_ps_comp_stmt): Likewise.
(pkl_trans1_pr_loop_stmt): Likewise.
(pkl_trans1_ps_loop_stmt): Likewise.
(pkl_trans1_pr_try_stmt_body): Likewise.
(pkl_trans1_ps_try_stmt_body): Likewise.
(pkl_trans1_pr_try_stmt): New handler.
(pkl_trans1_ps_try_stmt): Likewise.
(pkl_trans1_pr_try_stmt_handler): Likewise.
(pkl_trans1_ps_try_stmt_handler): Likewise.
(pkl_trans1_ps_break_stmt): Likewise.
(pkl_trans1_ps_continue_stmt): Likewise.
(pkl_phase_trans1): Register new handlers.
---
Hi Jose,
Changes:
- Add comments for trans handlers.
- Fix typo (s/escapable/breakable).
Regards,
Mohammad-Reza
ChangeLog | 27 +++++++++
libpoke/pkl-ast.c | 91 ----------------------------
libpoke/pkl-ast.h | 2 -
libpoke/pkl-tab.y | 30 ----------
libpoke/pkl-trans.c | 140 ++++++++++++++++++++++++++++++++++++++++++--
libpoke/pkl-trans.h | 27 ++++++++-
6 files changed, 188 insertions(+), 129 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index d6763f64..85bacb64 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2022-07-17 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
+
+ * libpoke/pkl-ast.h (pkl_ast_finish_breaks): Remove.
+ * libpoke/pkl-ast.c (pkl_ast_finish_breaks): Likewise.
+ (pkl_ast_finish_breaks_1): Likewise.
+ * libpoke/pkl-tab.y (stmt): Likewise.
+ * libpoke/pkl-trans.h (struct pkl_trans_escapable_ctx): New struct.
+ (PKL_TRANS_MAX_COMP_STMT_NEST): New macro.
+ (struct pkl_trans_payload): Add new fields.
+ * libpoke/pkl-trans.c (PKL_TRANS_ESCAPABLE): New macro.
+ (PKL_TRANS_PUSH_ESCAPABLE): Likewise.
+ (PKL_TRANS_POP_ESCAPABLE): Likewise.
+ (pkl_trans1_pr_comp_stmt): Add logic to track lexical frames around
+ `break` and `continue` keywords.
+ (pkl_trans1_ps_comp_stmt): Likewise.
+ (pkl_trans1_pr_loop_stmt): Likewise.
+ (pkl_trans1_ps_loop_stmt): Likewise.
+ (pkl_trans1_pr_try_stmt_body): Likewise.
+ (pkl_trans1_ps_try_stmt_body): Likewise.
+ (pkl_trans1_pr_try_stmt): New handler.
+ (pkl_trans1_ps_try_stmt): Likewise.
+ (pkl_trans1_pr_try_stmt_handler): Likewise.
+ (pkl_trans1_ps_try_stmt_handler): Likewise.
+ (pkl_trans1_ps_break_stmt): Likewise.
+ (pkl_trans1_ps_continue_stmt): Likewise.
+ (pkl_phase_trans1): Register new handlers.
+
2022-07-17 Mohammad-Reza Nabipoor <mnabipoor@gnu.org>
* etc/hacking.org (try_stmt): Update the topology.
diff --git a/libpoke/pkl-ast.c b/libpoke/pkl-ast.c
index 48d3e76c..697e70e8 100644
--- a/libpoke/pkl-ast.c
+++ b/libpoke/pkl-ast.c
@@ -2644,97 +2644,6 @@ pkl_ast_reverse (pkl_ast_node ast)
return prev;
}
-/* Annotate the break and continue statements within a given entity
- (loop or switch or...) with a pointer to the entity and their
- lexical nest level within the entity. */
-
-static void
-pkl_ast_finish_breaks_1 (pkl_ast_node entity, pkl_ast_node stmt,
- int *nframes)
-{
- /* STMT can be a statement or a declaration. */
-
- switch (PKL_AST_CODE (stmt))
- {
- case PKL_AST_BREAK_STMT:
- PKL_AST_BREAK_STMT_ENTITY (stmt) = entity; /* Note no ASTREF */
- PKL_AST_BREAK_STMT_NFRAMES (stmt) = *nframes;
- break;
- case PKL_AST_CONTINUE_STMT:
- PKL_AST_CONTINUE_STMT_ENTITY (stmt) = entity; /* Note no ASTREF */
- PKL_AST_CONTINUE_STMT_NFRAMES (stmt) = *nframes;
- break;
- case PKL_AST_COMP_STMT:
- {
- pkl_ast_node t;
-
- *nframes += 1;
- for (t = PKL_AST_COMP_STMT_STMTS (stmt); t;
- t = PKL_AST_CHAIN (t))
- pkl_ast_finish_breaks_1 (entity, t, nframes);
-
- /* Pop the frame of the compound itself. */
- *nframes -= 1;
- break;
- }
- case PKL_AST_IF_STMT:
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_IF_STMT_THEN_STMT (stmt),
- nframes);
- if (PKL_AST_IF_STMT_ELSE_STMT (stmt))
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_IF_STMT_ELSE_STMT (stmt),
- nframes);
- break;
- case PKL_AST_TRY_STMT_BODY:
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_TRY_STMT_BODY_CODE (stmt),
- nframes);
- break;
- case PKL_AST_TRY_STMT_HANDLER:
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_TRY_STMT_HANDLER_CODE (stmt),
- nframes);
- break;
- case PKL_AST_TRY_STMT:
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_TRY_STMT_BODY (stmt),
- nframes);
-
- if (PKL_AST_TRY_STMT_KIND (stmt) == PKL_AST_TRY_STMT_KIND_CATCH)
- {
- if (PKL_AST_TRY_STMT_ARG (stmt))
- *nframes += 1;
- pkl_ast_finish_breaks_1 (entity,
- PKL_AST_TRY_STMT_HANDLER (stmt),
- nframes);
- if (PKL_AST_TRY_STMT_ARG (stmt))
- *nframes -=1;
- }
- break;
- case PKL_AST_DECL:
- case PKL_AST_RETURN_STMT:
- case PKL_AST_LOOP_STMT:
- case PKL_AST_LOOP_STMT_ITERATOR:
- case PKL_AST_EXP_STMT:
- case PKL_AST_ASS_STMT:
- case PKL_AST_PRINT_STMT:
- case PKL_AST_RAISE_STMT:
- case PKL_AST_NULL_STMT:
- break;
- default:
- assert (0);
- break;
- }
-}
-
-void
-pkl_ast_finish_breaks (pkl_ast_node entity, pkl_ast_node stmt)
-{
- int nframes = 0;
- pkl_ast_finish_breaks_1 (entity, stmt, &nframes);
-}
-
pkl_ast_node
pkl_ast_type_incr_step (pkl_ast ast, pkl_ast_node type)
{
diff --git a/libpoke/pkl-ast.h b/libpoke/pkl-ast.h
index 6ad9992a..3f3bca7a 100644
--- a/libpoke/pkl-ast.h
+++ b/libpoke/pkl-ast.h
@@ -1928,8 +1928,6 @@ struct pkl_ast_break_stmt
pkl_ast_node pkl_ast_make_break_stmt (pkl_ast ast);
-void pkl_ast_finish_breaks (pkl_ast_node entity, pkl_ast_node stmt);
-
/* PKL_AST_RAISE_STMT nodes represent `raise' statements, which are
used in order to raise exceptions at the program level.
diff --git a/libpoke/pkl-tab.y b/libpoke/pkl-tab.y
index 89328436..a7675ab0 100644
--- a/libpoke/pkl-tab.y
+++ b/libpoke/pkl-tab.y
@@ -2334,11 +2334,6 @@ stmt:
NULL, /* tail */
$5); /* body */
PKL_AST_LOC ($$) = @$;
-
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $5);
}
| FOR '(' pushlevel simple_declaration ';' expression_opt ';'
simple_stmt_list ')' stmt
{
@@ -2351,11 +2346,6 @@ stmt:
$10); /* body */
PKL_AST_LOC ($$) = @$;
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $10);
-
/* Pop the frame introduced by `pushlevel'
above. */
pkl_parser->env = pkl_env_pop_frame (pkl_parser->env);
@@ -2370,11 +2360,6 @@ stmt:
$6, /* tail */
$8); /* body */
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $8);
-
PKL_AST_LOC ($$) = @$;
}
| FOR '(' IDENTIFIER IN expression pushlevel
@@ -2421,11 +2406,6 @@ stmt:
/* Free the identifier. */
$3 = ASTREF ($3); pkl_ast_node_free ($3);
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $9);
-
/* Pop the frame introduced by `pushlevel'
above. */
pkl_parser->env = pkl_env_pop_frame (pkl_parser->env);
@@ -2474,11 +2454,6 @@ stmt:
PKL_AST_LOC ($3) = @3;
PKL_AST_LOC ($$) = @$;
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $11);
-
/* Pop the frame introduced by `pushlevel'
above. */
pkl_parser->env = pkl_env_pop_frame (pkl_parser->env);
@@ -2562,11 +2537,6 @@ stmt:
NULL /* arg */, $4);
PKL_AST_LOC (body) = @2;
PKL_AST_LOC ($$) = @$;
-
- /* Annotate the contained BREAK and CONTINUE
- statements with their lexical level within this
- loop. */
- pkl_ast_finish_breaks ($$, $2);
}
| RAISE ';'
{
diff --git a/libpoke/pkl-trans.c b/libpoke/pkl-trans.c
index 768c8023..11be7a8a 100644
--- a/libpoke/pkl-trans.c
+++ b/libpoke/pkl-trans.c
@@ -107,6 +107,32 @@ pkl_trans_in_functions (struct pkl_trans_function_ctx
functions[],
} \
while (0)
+/* Handling of the stack of escapable constructions. */
+
+#define PKL_TRANS_ESCAPABLE \
+ (PKL_TRANS_PAYLOAD->next_escapable == 0 \
+ ? NULL \
+ : &PKL_TRANS_PAYLOAD->escapables[PKL_TRANS_PAYLOAD->next_escapable - 1])
+
+#define PKL_TRANS_PUSH_ESCAPABLE(b) \
+ do \
+ { \
+ assert (PKL_TRANS_PAYLOAD->next_escapable <
PKL_TRANS_MAX_COMP_STMT_NEST);\
+ PKL_TRANS_PAYLOAD->escapables[PKL_TRANS_PAYLOAD->next_escapable].nframes
\
+ = 0; \
+ PKL_TRANS_PAYLOAD->escapables[PKL_TRANS_PAYLOAD->next_escapable++].node \
+ = (b); \
+ } \
+ while (0)
+
+#define PKL_TRANS_POP_ESCAPABLE \
+ do \
+ { \
+ assert (PKL_TRANS_PAYLOAD->next_escapable > 0); \
+ PKL_TRANS_PAYLOAD->next_escapable--; \
+ } \
+ while (0)
+
/* The following handler is used in all trans phases and initializes
the phase payload. */
@@ -1101,6 +1127,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_comp_stmt)
PKL_TRANS_FUNCTION->npopes++;
}
}
+
+ if (PKL_TRANS_ESCAPABLE)
+ PKL_TRANS_ESCAPABLE->nframes++;
}
PKL_PHASE_END_HANDLER
@@ -1115,7 +1144,12 @@ PKL_PHASE_BEGIN_HANDLER
(pkl_trans1_ps_loop_stmt_iterator)
}
PKL_PHASE_END_HANDLER
-/* Likewise. */
+/* FOR statements introduce a lexical level if they use an iterator
+ or have a head of declarations. Update the current function
+ context accordingly.
+
+ FOR statements are escapable constructs, push it to current
+ escapables stack. */
PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_loop_stmt)
{
@@ -1130,10 +1164,12 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_loop_stmt)
if (PKL_TRANS_FUNCTION && PKL_AST_LOOP_STMT_ITERATOR (stmt))
PKL_TRANS_FUNCTION->ndrops += 3;
+
+ PKL_TRANS_PUSH_ESCAPABLE (stmt);
}
PKL_PHASE_END_HANDLER
-/* Likewise. */
+/* Revert what we did in `pkl_trans1_pr_loop_stmt'. */
PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_loop_stmt)
{
@@ -1146,6 +1182,8 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_loop_stmt)
if (PKL_TRANS_FUNCTION
&& (PKL_TRANS_FUNCTION && PKL_AST_LOOP_STMT_ITERATOR (stmt)))
PKL_TRANS_FUNCTION->ndrops -= 3;
+
+ PKL_TRANS_POP_ESCAPABLE;
}
PKL_PHASE_END_HANDLER
@@ -1153,7 +1191,7 @@ PKL_PHASE_END_HANDLER
function declarations occurring in the statement.
Compound statements introduce a lexical level. Update the current
- function context accordingly.
+ function context and current escapable context accordingly.
If the compound statement is the first operand of an excond
operator, then it increases the number of exception handlers that
@@ -1189,6 +1227,9 @@ PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_comp_stmt)
PKL_TRANS_FUNCTION->npopes--;
}
}
+
+ if (PKL_TRANS_ESCAPABLE)
+ PKL_TRANS_ESCAPABLE->nframes--;
}
PKL_PHASE_END_HANDLER
@@ -1238,23 +1279,106 @@ PKL_PHASE_END_HANDLER
/* The body of a try statement increases the number of exception
handlers that need to be eventually poped. Update the current
- function context accordingly. */
+ function context accordingly.
+
+ try-until statements are escapable constructs. Update escapables
+ stack accordingly. */
PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_try_stmt_body)
{
if (PKL_TRANS_FUNCTION)
PKL_TRANS_FUNCTION->npopes++;
+
+ if (PKL_AST_TRY_STMT_KIND (PKL_PASS_PARENT) == PKL_AST_TRY_STMT_KIND_UNTIL)
+ PKL_TRANS_PUSH_ESCAPABLE (PKL_PASS_PARENT);
}
PKL_PHASE_END_HANDLER
/* The body of a try statement increases the number of exception
handlers that need to be eventually poped. Update the current
- function context accordingly. */
+ function context accordingly.
+
+ try-until statements are escapable constructs. Update escapables
+ stack accordingly. */
PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_try_stmt_body)
{
if (PKL_TRANS_FUNCTION)
PKL_TRANS_FUNCTION->npopes--;
+
+ if (PKL_AST_TRY_STMT_KIND (PKL_PASS_PARENT) == PKL_AST_TRY_STMT_KIND_UNTIL)
+ PKL_TRANS_POP_ESCAPABLE;
+}
+PKL_PHASE_END_HANDLER
+
+/* The handler of a try-catch statement introduces a new lexical
+ level for escapable constructs. Update the current escapable
+ context. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_try_stmt_handler)
+{
+ if (PKL_TRANS_ESCAPABLE)
+ PKL_TRANS_ESCAPABLE->nframes++;
+}
+PKL_PHASE_END_HANDLER
+
+/* Likewise. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_try_stmt_handler)
+{
+ if (PKL_TRANS_ESCAPABLE)
+ PKL_TRANS_ESCAPABLE->nframes--;
+}
+PKL_PHASE_END_HANDLER
+
+/* try-until statements are escapable constructs. Update escapables
+ stack accordingly. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_pr_try_stmt)
+{
+ if (PKL_AST_TRY_STMT_KIND (PKL_PASS_NODE) == PKL_AST_TRY_STMT_KIND_UNTIL)
+ PKL_TRANS_PUSH_ESCAPABLE (PKL_PASS_NODE);
+}
+PKL_PHASE_END_HANDLER
+
+/* Likewise. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_try_stmt)
+{
+ if (PKL_AST_TRY_STMT_KIND (PKL_PASS_NODE) == PKL_AST_TRY_STMT_KIND_UNTIL)
+ PKL_TRANS_POP_ESCAPABLE;
+}
+PKL_PHASE_END_HANDLER
+
+/* Annotate break statements with enclosing escapable construct, and
+ with their lexical nesting level with respect to the enclosing
+ escapable construct. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_break_stmt)
+{
+ if (PKL_TRANS_ESCAPABLE)
+ {
+ PKL_AST_BREAK_STMT_ENTITY (PKL_PASS_NODE)
+ = PKL_TRANS_ESCAPABLE->node;
+ PKL_AST_BREAK_STMT_NFRAMES (PKL_PASS_NODE)
+ = PKL_TRANS_ESCAPABLE->nframes;
+ }
+}
+PKL_PHASE_END_HANDLER
+
+/* Annotate continue statements with enclosing escapable construct,
+ and with their lexical nesting level with respect to the enclosing
+ escapable construct. */
+
+PKL_PHASE_BEGIN_HANDLER (pkl_trans1_ps_continue_stmt)
+{
+ if (PKL_TRANS_ESCAPABLE)
+ {
+ PKL_AST_CONTINUE_STMT_ENTITY (PKL_PASS_NODE)
+ = PKL_TRANS_ESCAPABLE->node;
+ PKL_AST_CONTINUE_STMT_NFRAMES (PKL_PASS_NODE)
+ = PKL_TRANS_ESCAPABLE->nframes;
+ }
}
PKL_PHASE_END_HANDLER
@@ -1292,7 +1416,13 @@ struct pkl_phase pkl_phase_trans1 =
PKL_PHASE_PS_HANDLER (PKL_AST_LOOP_STMT_ITERATOR,
pkl_trans1_ps_loop_stmt_iterator),
PKL_PHASE_PR_HANDLER (PKL_AST_LOOP_STMT, pkl_trans1_pr_loop_stmt),
PKL_PHASE_PS_HANDLER (PKL_AST_LOOP_STMT, pkl_trans1_ps_loop_stmt),
+ PKL_PHASE_PS_HANDLER (PKL_AST_BREAK_STMT, pkl_trans1_ps_break_stmt),
+ PKL_PHASE_PS_HANDLER (PKL_AST_CONTINUE_STMT, pkl_trans1_ps_continue_stmt),
+ PKL_PHASE_PR_HANDLER (PKL_AST_TRY_STMT_BODY, pkl_trans1_pr_try_stmt),
+ PKL_PHASE_PS_HANDLER (PKL_AST_TRY_STMT_BODY, pkl_trans1_ps_try_stmt),
PKL_PHASE_PR_HANDLER (PKL_AST_TRY_STMT_BODY, pkl_trans1_pr_try_stmt_body),
+ PKL_PHASE_PS_HANDLER (PKL_AST_TRY_STMT_HANDLER,
pkl_trans1_ps_try_stmt_handler),
+ PKL_PHASE_PR_HANDLER (PKL_AST_TRY_STMT_HANDLER,
pkl_trans1_pr_try_stmt_handler),
PKL_PHASE_PS_HANDLER (PKL_AST_TRY_STMT_BODY, pkl_trans1_ps_try_stmt_body),
PKL_PHASE_PR_HANDLER (PKL_AST_STRUCT_TYPE_FIELD,
pkl_trans1_pr_struct_type_field),
PKL_PHASE_PS_HANDLER (PKL_AST_STRUCT_TYPE_FIELD,
pkl_trans1_ps_struct_type_field),
diff --git a/libpoke/pkl-trans.h b/libpoke/pkl-trans.h
index 8d3b1f6f..5a220e3d 100644
--- a/libpoke/pkl-trans.h
+++ b/libpoke/pkl-trans.h
@@ -53,6 +53,23 @@ struct pkl_trans_function_ctx
struct pkl_trans_function_ctx *next;
};
+/* The trans phases keep a stack of escapable entities (loops and
+ try-until statements) and the corresponding `break' and `continue'
+ keywords, while they operate on the AST.
+
+ The following struct implements each entry on the breakable/continuable
+ entities stack.
+
+ NODE is the escapable entity (loop or try-until statement).
+
+ NFRAMES is the number of frames in the body of NODE. */
+
+struct pkl_trans_escapable_ctx
+{
+ pkl_ast_node node;
+ int nframes;
+};
+
/* The following struct defines the payload of the trans phases.
ERRORS is the number of errors detected while running the phase.
@@ -69,10 +86,16 @@ struct pkl_trans_function_ctx
when mapping and writing integral types.
CUR_ENDIAN is the index to ENDIAN and marks the top of the stack of
- endianness. Initially PKL_AST_ENDIAN_DFL. */
+ endianness. Initially PKL_AST_ENDIAN_DFL.
+
+ ESCAPABLES is a stack of escapables.
+
+ NEXT_ESCAPABLE - 1 is the index for the enclosing escapable
+ entity. */
#define PKL_TRANS_MAX_FUNCTION_NEST 32
#define PKL_TRANS_MAX_ENDIAN 25
+#define PKL_TRANS_MAX_COMP_STMT_NEST 32
struct pkl_trans_payload
{
@@ -82,6 +105,8 @@ struct pkl_trans_payload
int next_function;
enum pkl_ast_endian endian[PKL_TRANS_MAX_ENDIAN];
int cur_endian;
+ struct pkl_trans_escapable_ctx escapables[PKL_TRANS_MAX_COMP_STMT_NEST];
+ int next_escapable;
};
typedef struct pkl_trans_payload *pkl_trans_payload;
--
2.37.1