From 5df65f41c94dd0ac993861089a9a8716c3fbf6ec Mon Sep 17 00:00:00 2001 From: Jean <47366872+jean-voila@users.noreply.github.com> Date: Sat, 31 Jan 2026 16:43:52 +0100 Subject: [PATCH] feat(execution): Implemented break and continue for while --- src/execution/execution_helpers.c | 71 ++++++++++++++++++++++++++++--- src/execution/execution_helpers.h | 4 ++ 2 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/execution/execution_helpers.c b/src/execution/execution_helpers.c index ebb833d..5157290 100644 --- a/src/execution/execution_helpers.c +++ b/src/execution/execution_helpers.c @@ -123,6 +123,9 @@ static char **list_to_argv(struct list *command_list) static int try_builtin(char **argv, struct hash_map *vars); +static int builtin_break(char **argv); +static int builtin_continue(char **argv); + static int exec_assignment(struct list *assignment_list, struct hash_map *vars) { while (assignment_list != NULL) @@ -202,10 +205,22 @@ int exec_ast_if(struct ast_if *if_node, struct hash_map *vars) if (if_node == NULL) return 2; int cond = execution(if_node->condition, vars); + if (cond == EXEC_SIGNAL_BREAK || cond == EXEC_SIGNAL_CONTINUE) + return cond; if (cond == 0) - return execution(if_node->then_clause, vars); + { + int r = execution(if_node->then_clause, vars); + if (r == EXEC_SIGNAL_BREAK || r == EXEC_SIGNAL_CONTINUE) + return r; + return r; + } else - return execution(if_node->else_clause, vars); + { + int r = execution(if_node->else_clause, vars); + if (r == EXEC_SIGNAL_BREAK || r == EXEC_SIGNAL_CONTINUE) + return r; + return r; + } } int exec_ast_list(struct ast_list *list_node, struct hash_map *vars) @@ -216,7 +231,13 @@ int exec_ast_list(struct ast_list *list_node, struct hash_map *vars) { struct ast *child = (struct ast *)cur->data; if (!ast_is_void(child)) - ret = execution(child, vars); + { + int child_ret = execution(child, vars); + if (child_ret == EXEC_SIGNAL_BREAK + || child_ret == EXEC_SIGNAL_CONTINUE) + return child_ret; + ret = child_ret; + } cur = cur->next; } return ret; @@ -225,16 +246,30 @@ int exec_ast_list(struct ast_list *list_node, struct hash_map *vars) int exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars) { int left_ret = execution(ao_node->left, vars); + if (left_ret == EXEC_SIGNAL_BREAK || left_ret == EXEC_SIGNAL_CONTINUE) + return left_ret; if (ao_node->type == AST_AND_OR_TYPE_AND) { if (left_ret == 0) - return execution(ao_node->right, vars); + { + int right_ret = execution(ao_node->right, vars); + if (right_ret == EXEC_SIGNAL_BREAK + || right_ret == EXEC_SIGNAL_CONTINUE) + return right_ret; + return right_ret; + } return left_ret; } else { if (left_ret != 0) - return execution(ao_node->right, vars); + { + int right_ret = execution(ao_node->right, vars); + if (right_ret == EXEC_SIGNAL_BREAK + || right_ret == EXEC_SIGNAL_CONTINUE) + return right_ret; + return right_ret; + } return left_ret; } } @@ -279,6 +314,16 @@ int exec_ast_loop(struct ast_loop *loop_node, struct hash_map *vars) while (execution(loop_node->condition, vars) == 0) { res = execution(loop_node->body, vars); + if (res == EXEC_SIGNAL_BREAK) + { + res = 0; + break; + } + else if (res == EXEC_SIGNAL_CONTINUE) + { + res = 0; + continue; + } } return res; @@ -385,6 +430,18 @@ static int builtin_echo(char **argv) return 0; } +static int builtin_break(char **argv) +{ + (void)argv; + return EXEC_SIGNAL_BREAK; +} + +static int builtin_continue(char **argv) +{ + (void)argv; + return EXEC_SIGNAL_CONTINUE; +} + static int builtin_true(char **argv) { (void)argv; @@ -447,6 +504,10 @@ static int try_builtin(char **argv, struct hash_map *vars) return builtin_true(argv); if (strcmp(argv[0], "false") == 0) return builtin_false(argv); + if (strcmp(argv[0], "break") == 0) + return builtin_break(argv); + if (strcmp(argv[0], "continue") == 0) + return builtin_continue(argv); if (strcmp(argv[0], "exit") == 0) return builtin_exit(argv); if (strcmp(argv[0], "cd") == 0) diff --git a/src/execution/execution_helpers.h b/src/execution/execution_helpers.h index 1716179..530b4dc 100644 --- a/src/execution/execution_helpers.h +++ b/src/execution/execution_helpers.h @@ -4,6 +4,10 @@ #include "../utils/ast/ast.h" #include "../utils/hash_map/hash_map.h" +// Special execution signals used internally to implement loop control +#define EXEC_SIGNAL_CONTINUE (-2) +#define EXEC_SIGNAL_BREAK (-3) + int exec_ast_command(struct ast_command *command, struct hash_map *vars); int exec_ast_if(struct ast_if *if_node, struct hash_map *vars); int exec_ast_list(struct ast_list *list_node, struct hash_map *vars);