parser+codegen: Add support for 'return' statement

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-02-16 13:49:15 -05:00
parent 3d6cc301f3
commit 3e8a45a156
4 changed files with 212 additions and 1 deletions

View File

@@ -25,6 +25,48 @@ resolve_func(struct rifle_state *state, struct ast_node *root)
return mu_gen_label(state, symbol->name, symbol->pub);
}
static int
resolve_return(struct rifle_state *state, struct ast_node *root)
{
struct symbol *func_sym;
struct ast_node *rhs;
data_type_t type;
if (state == NULL || root == NULL) {
return -1;
}
if ((func_sym = state->cur_func) == NULL) {
return -1;
}
if (root->type != AST_RETURN) {
return -1;
}
if ((rhs = root->right) == NULL) {
trace_error(state, "internal: return has no rhs\n");
return -1;
}
type = data_raw_type(&func_sym->dtype) ;
switch (rhs->type) {
case AST_NUMBER:
mu_gen_retimm(
state,
rhs->v,
type_to_msize(type)
);
break;
default:
trace_error(state, "internal: bad ast node in return\n");
return -1;
}
return 0;
}
int
cg_resolve_node(struct rifle_state *state, struct ast_node *root)
{
@@ -38,6 +80,12 @@ cg_resolve_node(struct rifle_state *state, struct ast_node *root)
return -1;
}
break;
case AST_RETURN:
if (resolve_return(state, root) < 0) {
return -1;
}
break;
default:
trace_error(state, "unknown ast node %d\n", root->type);

View File

@@ -547,6 +547,123 @@ parse_rbrace(struct rifle_state *state, struct token *tok, struct ast_node **res
return 0;
}
/*
* Parse a value
*
* @state: Compiler state
* @tok: Last token
* @res: AST result
*
* Returns zero on success
*/
static int
parse_value(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;
}
switch (tok->type) {
case TT_NUMBER:
if (ast_alloc_node(state, AST_NUMBER, &root) < 0) {
trace_error(state, "failed to allocate AST_NUMBER\n");
return -1;
}
root->v = tok->v;
*res = root;
return 0;
default:
utok(state, symtok("number"), tokstr(tok));
break;
}
return -1;
}
/*
* Parse a binary expression
*
* @state: Compiler state
* @tok: Last token
* @res: AST result
*
* Returns zero on success
*/
static int
parse_binexpr(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 (parse_value(state, tok, &root) < 0) {
return -1;
}
/* TODO: Allow actual binary expressions */
*res = root;
return 0;
}
/*
* Parse a 'return' token
*
* @state: Compiler state
* @tok: Last token
* @res: AST result
*
* Returns zero on success
*/
static int
parse_return(struct rifle_state *state, struct token *tok, struct ast_node **res)
{
struct ast_node *root, *rhs;
if (state == NULL || tok == NULL) {
return -1;
}
if (res == NULL) {
return -1;
}
if (state->cur_func == NULL) {
trace_error(state, "'return' not in function\n");
return -1;
}
if (parse_scan(state, tok) < 0) {
ueof(state);
return -1;
}
if (parse_binexpr(state, tok, &rhs) < 0) {
return -1;
}
if (ast_alloc_node(state, AST_RETURN, &root) < 0) {
trace_error(state, "failed to allocate AST_RETURN\n");
return -1;
}
root->right = rhs;
*res = root;
return 0;
}
static int
parse_begin(struct rifle_state *state)
{
@@ -566,6 +683,12 @@ parse_begin(struct rifle_state *state)
return -1;
}
break;
case TT_RETURN:
if (parse_return(state, &tok, &root) < 0) {
return -1;
}
break;
case TT_PUB:
break;