feat(execution): Implemented break and continue for while
This commit is contained in:
parent
37e430a234
commit
5df65f41c9
2 changed files with 70 additions and 5 deletions
|
|
@ -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 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)
|
static int exec_assignment(struct list *assignment_list, struct hash_map *vars)
|
||||||
{
|
{
|
||||||
while (assignment_list != NULL)
|
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)
|
if (if_node == NULL)
|
||||||
return 2;
|
return 2;
|
||||||
int cond = execution(if_node->condition, vars);
|
int cond = execution(if_node->condition, vars);
|
||||||
|
if (cond == EXEC_SIGNAL_BREAK || cond == EXEC_SIGNAL_CONTINUE)
|
||||||
|
return cond;
|
||||||
if (cond == 0)
|
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
|
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)
|
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;
|
struct ast *child = (struct ast *)cur->data;
|
||||||
if (!ast_is_void(child))
|
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;
|
cur = cur->next;
|
||||||
}
|
}
|
||||||
return ret;
|
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 exec_ast_and_or(struct ast_and_or *ao_node, struct hash_map *vars)
|
||||||
{
|
{
|
||||||
int left_ret = execution(ao_node->left, 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 (ao_node->type == AST_AND_OR_TYPE_AND)
|
||||||
{
|
{
|
||||||
if (left_ret == 0)
|
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;
|
return left_ret;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (left_ret != 0)
|
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;
|
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)
|
while (execution(loop_node->condition, vars) == 0)
|
||||||
{
|
{
|
||||||
res = execution(loop_node->body, vars);
|
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;
|
return res;
|
||||||
|
|
@ -385,6 +430,18 @@ static int builtin_echo(char **argv)
|
||||||
return 0;
|
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)
|
static int builtin_true(char **argv)
|
||||||
{
|
{
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
@ -447,6 +504,10 @@ static int try_builtin(char **argv, struct hash_map *vars)
|
||||||
return builtin_true(argv);
|
return builtin_true(argv);
|
||||||
if (strcmp(argv[0], "false") == 0)
|
if (strcmp(argv[0], "false") == 0)
|
||||||
return builtin_false(argv);
|
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)
|
if (strcmp(argv[0], "exit") == 0)
|
||||||
return builtin_exit(argv);
|
return builtin_exit(argv);
|
||||||
if (strcmp(argv[0], "cd") == 0)
|
if (strcmp(argv[0], "cd") == 0)
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,10 @@
|
||||||
#include "../utils/ast/ast.h"
|
#include "../utils/ast/ast.h"
|
||||||
#include "../utils/hash_map/hash_map.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_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_if(struct ast_if *if_node, struct hash_map *vars);
|
||||||
int exec_ast_list(struct ast_list *list_node, struct hash_map *vars);
|
int exec_ast_list(struct ast_list *list_node, struct hash_map *vars);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue