stage1 支持label break, continue
This commit is contained in:
1 parent
3175e04e6e
commit
983746c797
5 files changed
+207
-36
No files matched your search
+89
-3
@@ -1400,20 +1400,48 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_EXPR_WHILE: {
|
||||
const char *lbl = NULL;
|
||||
if (n->while_expr.label) {
|
||||
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->while_expr.label);
|
||||
if (ln && ln->kind == SPL_AST_LABEL)
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
vec_push(sema->label_stack, lbl);
|
||||
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_check(sema, n->while_expr.cond, bt);
|
||||
if (n->while_expr.body)
|
||||
sema_infer(sema, n->while_expr.body);
|
||||
if (n->while_expr.else_branch)
|
||||
sema_infer(sema, n->while_expr.else_branch);
|
||||
|
||||
vec_pop(sema->label_stack);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_EXPR_LOOP: {
|
||||
const char *lbl = NULL;
|
||||
if (n->loop_expr.label) {
|
||||
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->loop_expr.label);
|
||||
if (ln && ln->kind == SPL_AST_LABEL)
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
vec_push(sema->label_stack, lbl);
|
||||
|
||||
if (n->loop_expr.body)
|
||||
sema_infer(sema, n->loop_expr.body);
|
||||
|
||||
vec_pop(sema->label_stack);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_EXPR_FOR: {
|
||||
const char *lbl = NULL;
|
||||
if (n->for_expr.label) {
|
||||
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->for_expr.label);
|
||||
if (ln && ln->kind == SPL_AST_LABEL)
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
vec_push(sema->label_stack, lbl);
|
||||
|
||||
sema_push_scope(sema);
|
||||
for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) {
|
||||
spl_lang_type_id_t container_tid = sema_infer(sema, vec_at(n->for_expr.iter_exprs, i));
|
||||
@@ -1439,6 +1467,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (n->for_expr.else_branch)
|
||||
sema_infer(sema, n->for_expr.else_branch);
|
||||
sema_pop_scope(sema);
|
||||
|
||||
vec_pop(sema->label_stack);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_EXPR_MATCH: {
|
||||
@@ -1711,9 +1741,64 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_STATEMENT_BREAK:
|
||||
case SPL_AST_STATEMENT_CONTINUE:
|
||||
case SPL_AST_STATEMENT_BREAK: {
|
||||
const char *lbl = NULL;
|
||||
if (n->statement_break.label) {
|
||||
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->statement_break.label);
|
||||
if (ln && ln->kind == SPL_AST_LABEL)
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
if (vec_size(sema->label_stack) == 0) {
|
||||
SPL_ERROR(&n->dbg, "`break` outside of loop");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
if (lbl) {
|
||||
bool found = false;
|
||||
for (usize i = vec_size(sema->label_stack); i > 0; --i) {
|
||||
const char *cur = vec_at(sema->label_stack, i - 1);
|
||||
if (cur && strcmp(cur, lbl) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||
sema->error_count++;
|
||||
}
|
||||
}
|
||||
if (n->statement_break.expr)
|
||||
sema_infer(sema, n->statement_break.expr);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_STATEMENT_CONTINUE: {
|
||||
const char *lbl = NULL;
|
||||
if (n->statement_continue.label) {
|
||||
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->statement_continue.label);
|
||||
if (ln && ln->kind == SPL_AST_LABEL)
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
if (vec_size(sema->label_stack) == 0) {
|
||||
SPL_ERROR(&n->dbg, "`continue` outside of loop");
|
||||
sema->error_count++;
|
||||
return 0;
|
||||
}
|
||||
if (lbl) {
|
||||
bool found = false;
|
||||
for (usize i = vec_size(sema->label_stack); i > 0; --i) {
|
||||
const char *cur = vec_at(sema->label_stack, i - 1);
|
||||
if (cur && strcmp(cur, lbl) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||
sema->error_count++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_STATEMENT_DEFER:
|
||||
if (n->statement_defer.body)
|
||||
sema_infer(sema, n->statement_defer.body);
|
||||
@@ -1754,9 +1839,10 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
|
||||
sema->attr = attr;
|
||||
sema->root = (spl_symbol_t){0};
|
||||
sema->store_scope = 0;
|
||||
vec_init(sema->label_stack);
|
||||
}
|
||||
|
||||
void spl_sema_drop(spl_sema_t *sema) { (void)sema; }
|
||||
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
|
||||
|
||||
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
|
||||
if (!sema->ast || !module_ref)
|
||||
|
||||
Reference in new issue
Block a user