parser+codegen: Add support for loops
Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
@@ -67,6 +67,29 @@ resolve_return(struct rifle_state *state, struct ast_node *root)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
resolve_loop(struct rifle_state *state, struct ast_node *root)
|
||||
{
|
||||
char label[32];
|
||||
|
||||
if (state == NULL || root == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (root->epilogue) {
|
||||
snprintf(label, sizeof(label), "L.%zu", state->loop_count - 1);
|
||||
mu_gen_blab(state, label);
|
||||
|
||||
snprintf(label, sizeof(label), "L.%zu.1", state->loop_count - 1);
|
||||
mu_gen_label(state, label, false);
|
||||
} else {
|
||||
snprintf(label, sizeof(label), "L.%zu", state->loop_count++);
|
||||
mu_gen_label(state, label, false);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
cg_resolve_node(struct rifle_state *state, struct ast_node *root)
|
||||
{
|
||||
@@ -86,6 +109,12 @@ cg_resolve_node(struct rifle_state *state, struct ast_node *root)
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case AST_LOOP:
|
||||
if (resolve_loop(state, root) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
trace_error(state, "unknown ast node %d\n", root->type);
|
||||
|
||||
@@ -545,6 +545,14 @@ parse_rbrace(struct rifle_state *state, struct token *tok, struct ast_node **res
|
||||
return -1;
|
||||
}
|
||||
|
||||
root->epilogue = 1;
|
||||
break;
|
||||
case TT_LOOP:
|
||||
if (ast_alloc_node(state, AST_LOOP, &root) < 0) {
|
||||
trace_error(state, "failed to allocate AST_LOOP\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
root->epilogue = 1;
|
||||
break;
|
||||
default:
|
||||
@@ -677,6 +685,45 @@ parse_return(struct rifle_state *state, struct token *tok, struct ast_node **res
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse a loop statement
|
||||
*
|
||||
* @state: Compiler state
|
||||
* @tok: Last token
|
||||
* @res: AST result
|
||||
*
|
||||
* Returns zero on success
|
||||
*/
|
||||
static int
|
||||
parse_loop(struct rifle_state *state, struct token *tok, struct ast_node **res)
|
||||
{
|
||||
struct ast_node *root;
|
||||
|
||||
if (state == NULL || tok == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (res == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (tok->type != TT_LOOP) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parse_lbrace(state, TT_LOOP, tok) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ast_alloc_node(state, AST_LOOP, &root) < 0) {
|
||||
trace_error(state, "failed to allocate AST_LOOP\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
*res = root;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
parse_begin(struct rifle_state *state)
|
||||
{
|
||||
@@ -702,6 +749,12 @@ parse_begin(struct rifle_state *state)
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case TT_LOOP:
|
||||
if (parse_loop(state, &tok, &root) < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
break;
|
||||
case TT_PUB:
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user