stage1 重写进行代码设计并重构 提供diag替换老旧错误处理
This commit is contained in:
1 parent
7cbe2d2b9a
commit
e4347cc3ea
14 files changed
+983
-526
No files matched your search
+186
-221
@@ -27,16 +27,11 @@ spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) {
|
||||
}
|
||||
|
||||
bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) {
|
||||
if (!id || id >= vec_size(scope->scopes)) {
|
||||
LOG_FATAL("sema scope insert error");
|
||||
return false;
|
||||
}
|
||||
Assert(id != 0 && id < vec_size(scope->scopes));
|
||||
spl_scope_node_t *node = &vec_at(scope->scopes, id);
|
||||
spl_symbol_t old = {0};
|
||||
if (map_get(node->symbols, symbol.name, &old)) {
|
||||
SPL_ERROR(&(spl_dbg_node_t){0}, "duplicate symbol `%s`", symbol.name);
|
||||
if (map_get(node->symbols, symbol.name, &old))
|
||||
return false;
|
||||
}
|
||||
map_put(node->symbols, symbol.name, symbol);
|
||||
return true;
|
||||
}
|
||||
@@ -46,9 +41,8 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) {
|
||||
return false;
|
||||
for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) {
|
||||
spl_scope_node_t *s = &vec_at(scope->scopes, id);
|
||||
if (map_get(s->symbols, name, out)) {
|
||||
if (map_get(s->symbols, name, out))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -83,16 +77,16 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
||||
|
||||
spl_attr_info_t *info = spl_attr_lookup(sema->attr, NULL, a->tag_item.name);
|
||||
if (!info) {
|
||||
SPL_ERROR(&a->dbg, "unknown attribute `%s`", a->tag_item.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||
"unknown attribute `%s`", a->tag_item.name);
|
||||
continue;
|
||||
}
|
||||
|
||||
usize nargs = vec_size(a->tag_item.args);
|
||||
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
||||
SPL_ERROR(&a->dbg, "attribute `%s` expects %d..%d args, got %zu", info->name,
|
||||
info->min_args, info->max_args, nargs);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||
"attribute `%s` expects %d..%d args, got %zu", info->name,
|
||||
info->min_args, info->max_args, nargs);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -120,8 +114,8 @@ static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw,
|
||||
oa.value.i = arg->int_lit.bits;
|
||||
break;
|
||||
default:
|
||||
SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_ATTR, &a->dbg,
|
||||
"attribute arg #%zu has unsupported form", j);
|
||||
bad = 1;
|
||||
break;
|
||||
}
|
||||
@@ -162,21 +156,6 @@ static spl_lang_type_id_t sema_lang_from_ir(spl_sema_t *sema, spl_type_id_t ir)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool sema_is_literal(spl_ast_node_t *n) {
|
||||
switch (n->kind) {
|
||||
case SPL_AST_EXPR_INT_LIT:
|
||||
case SPL_AST_EXPR_FLOAT_LIT:
|
||||
case SPL_AST_EXPR_CHAR_LIT:
|
||||
case SPL_AST_EXPR_STRING_LIT:
|
||||
case SPL_AST_EXPR_BOOL_LIT:
|
||||
case SPL_AST_EXPR_NULL_LIT:
|
||||
case SPL_AST_EXPR_UNDEFINED_LIT:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf, usize cap) {
|
||||
if (!buf || cap == 0)
|
||||
return;
|
||||
@@ -255,17 +234,14 @@ static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf
|
||||
|
||||
static inline void sema_push_scope(spl_sema_t *sema) {
|
||||
spl_scope_id_t new_scope = spl_scope_alloc(sema->scope);
|
||||
sema->store_scope = sema->scope->current_scope;
|
||||
sema->scope->current_scope = new_scope;
|
||||
}
|
||||
|
||||
static inline void sema_pop_scope(spl_sema_t *sema) {
|
||||
spl_scope_id_t cur = sema->scope->current_scope;
|
||||
if (cur != 0 && cur < vec_size(sema->scope->scopes)) {
|
||||
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
|
||||
} else {
|
||||
sema->scope->current_scope = sema->store_scope;
|
||||
}
|
||||
if (cur == 0 || cur >= vec_size(sema->scope->scopes))
|
||||
Panic("sema_pop_scope: bad current_scope %zu", cur);
|
||||
sema->scope->current_scope = vec_at(sema->scope->scopes, cur).parent;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
|
||||
@@ -394,8 +370,8 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id)
|
||||
}
|
||||
|
||||
if (def->state == SPL_DECL_RESOLVING) {
|
||||
SPL_ERROR(&def->dbg_node, "circular dependency on `%s`", def->name ? def->name : "?");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CIRCULAR_DEP, &def->dbg_node,
|
||||
"circular dependency on `%s`", def->name ? def->name : "?");
|
||||
def->state = SPL_DECL_ERROR;
|
||||
return 0;
|
||||
}
|
||||
@@ -457,13 +433,11 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
|
||||
switch (n->kind) {
|
||||
case SPL_AST_CONTAINER_MEMBERS: {
|
||||
/* root_scope 只在第一次创建,后续 module 复用 */
|
||||
if (sema->scope->root_scope == 0) {
|
||||
spl_scope_id_t root = spl_scope_alloc(sema->scope);
|
||||
sema->scope->root_scope = root;
|
||||
}
|
||||
|
||||
/* 进入 root_scope,再为当前 module 开一个子 scope */
|
||||
sema->scope->current_scope = sema->scope->root_scope;
|
||||
spl_scope_id_t mod_scope = spl_scope_alloc(sema->scope);
|
||||
sema->scope->current_scope = mod_scope;
|
||||
@@ -476,18 +450,14 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
|
||||
sema_collect_names(sema, vec_at(n->container_members.declarations, i));
|
||||
}
|
||||
|
||||
/* 故意不恢复 current_scope
|
||||
保持 mod_scope 交给随后的 sema_parse 使用。
|
||||
恢复由 spl_sema_run_module 统一负责 */
|
||||
break;
|
||||
}
|
||||
case SPL_AST_TYPE_DECL: {
|
||||
spl_symbol_t sym = {.name = n->type_decl.name, .kind = SPL_SYMBOL_KIND_TYPE};
|
||||
spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr);
|
||||
if (!te) {
|
||||
SPL_ERROR(&n->dbg, "type declaration `%s` missing type expression", n->type_decl.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"type declaration `%s` missing type expression", n->type_decl.name);
|
||||
return;
|
||||
}
|
||||
if (te->kind == SPL_AST_TYPE_AGGREGATE)
|
||||
@@ -495,14 +465,20 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
else
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref);
|
||||
n->resolved_def_id = sym.node;
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||
"duplicate symbol `%s`", sym.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPL_AST_FN_DECL: {
|
||||
spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN};
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, ref);
|
||||
n->resolved_def_id = sym.node;
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||
"duplicate symbol `%s`", sym.name);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPL_AST_VAR_DECL:
|
||||
@@ -513,17 +489,19 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
||||
n->resolved_def_id = sym.node;
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||
"duplicate symbol `%s`", name);
|
||||
}
|
||||
} else {
|
||||
SPL_ERROR(&n->dbg, "unsupported variable pattern (only simple identifier)");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"unsupported variable pattern (only simple identifier)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPL_AST_TOP_LEVEL_BLOCK:
|
||||
if (n->top_level_block.block) {
|
||||
if (n->top_level_block.block)
|
||||
sema_collect_names(sema, n->top_level_block.block);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -572,9 +550,9 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
const spl_intrin_info_t *info = spl_intrin_info(in);
|
||||
usize nargs = vec_size(*args);
|
||||
if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) {
|
||||
SPL_ERROR(&n->dbg, "`%s` expects %d..%d args, got %zu", info->name, info->min_args,
|
||||
info->max_args, nargs);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_INTRIN_ARG_COUNT, &n->dbg,
|
||||
"`%s` expects %d..%d args, got %zu", info->name, info->min_args,
|
||||
info->max_args, nargs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -599,7 +577,6 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
case SPL_INTRIN_FLOAT_FROM_INT:
|
||||
case SPL_INTRIN_PTR_FROM_INT:
|
||||
case SPL_INTRIN_PTR_CAST: {
|
||||
/* 双参数形式:源表达式 + 目标类型 */
|
||||
spl_lang_type_id_t src_lang = sema_infer(sema, vec_at(*args, 0));
|
||||
if (!src_lang)
|
||||
return 0;
|
||||
@@ -610,17 +587,15 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
||||
spl_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt);
|
||||
if (expected == SPL_INTRIN_NONE) {
|
||||
SPL_ERROR(&n->dbg, "`%s`: incompatible types", info->name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||
"`%s`: incompatible types", info->name);
|
||||
return 0;
|
||||
}
|
||||
/* 允许显式 builtin 覆盖 as 的默认选择(例如用 @int_cast 代替 @truncate) */
|
||||
n->resolved_lang_tid = dst_lang;
|
||||
return dst_lang;
|
||||
}
|
||||
case SPL_INTRIN_INT_FROM_BOOL:
|
||||
case SPL_INTRIN_INT_FROM_PTR: {
|
||||
/* 单参数:目标类型默认 usize;双参数时以第二参数为准 */
|
||||
sema_infer(sema, vec_at(*args, 0));
|
||||
if (nargs >= 2) {
|
||||
spl_lang_type_id_t dst = sema_infer(sema, vec_at(*args, 1));
|
||||
@@ -655,6 +630,34 @@ static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_block_body(spl_sema_t *sema, spl_ast_node_t *n,
|
||||
spl_lang_type_id_t expected) {
|
||||
spl_ast_node_ref_t tail = n->block.tail_expr;
|
||||
|
||||
sema_push_scope(sema);
|
||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
||||
|
||||
spl_lang_type_id_t r = 0;
|
||||
if (tail) {
|
||||
if (expected) {
|
||||
r = sema_coerce(sema, tail, expected);
|
||||
if (!r) {
|
||||
sema_pop_scope(sema);
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
r = sema_infer(sema, tail);
|
||||
}
|
||||
} else {
|
||||
r = spl_lang_make_unit(sema->type);
|
||||
}
|
||||
sema_pop_scope(sema);
|
||||
|
||||
n->resolved_lang_tid = r;
|
||||
return r;
|
||||
}
|
||||
|
||||
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t expected) {
|
||||
if (!ref || !expected)
|
||||
@@ -671,13 +674,11 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
if (already != 0) {
|
||||
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already);
|
||||
spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL;
|
||||
/* comptime 与 infer 都属于"可重定型":清空 resolved 后按 expected 重新推导 */
|
||||
bool a_rebindable =
|
||||
(an && an->kind == SPL_LANG_TYPE_INFER) ||
|
||||
(an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) ||
|
||||
(an && an->kind == SPL_LANG_TYPE_FLOAT && air && air->float_type.bits == 0);
|
||||
if (!a_rebindable) {
|
||||
/* 具体类型:只接受子类型方向 */
|
||||
if (spl_lang_type_is_subtype(sema->type, already, expected)) {
|
||||
n->expected_lang_tid = expected;
|
||||
return expected;
|
||||
@@ -685,12 +686,11 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
char ebuf[128], gbuf[128];
|
||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||
sema_type_to_str(sema, already, gbuf, sizeof(gbuf));
|
||||
SPL_ERROR(&n->dbg, "type mismatch: node kind=%d already typed as %s, expected %s",
|
||||
(int)n->kind, gbuf, ebuf);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"type mismatch: node kind=%d already typed as %s, expected %s",
|
||||
(int)n->kind, gbuf, ebuf);
|
||||
return 0;
|
||||
}
|
||||
/* 清空 resolved,走未定型路径,让递归按 expected 下推子节点 */
|
||||
n->resolved_lang_tid = 0;
|
||||
}
|
||||
|
||||
@@ -698,9 +698,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
switch (n->kind) {
|
||||
|
||||
case SPL_AST_EXPR_UNARY: {
|
||||
/* ADDRESS / DEREF 的结果类型由操作数决定,不能用 expected 反向定型。
|
||||
* 但不能直接 return ——— 那会绕过 expected 兼容性检查。
|
||||
* 走 break 落到兜底:infer 后做 is_subtype / comptime 判定。 */
|
||||
if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF)
|
||||
break;
|
||||
if (!sema_coerce(sema, n->unary.operand, expected))
|
||||
@@ -743,8 +740,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
return 0;
|
||||
}
|
||||
sema_coerce(sema, n->binary.left, common);
|
||||
@@ -754,8 +751,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
return b;
|
||||
}
|
||||
|
||||
/* ptr +/- int:expected 是 ptr 且左侧推断为 ptr。
|
||||
* 右侧保留原整型;仅 comptime_int(bits==0)收紧到 isize。 */
|
||||
if (op == SPL_OP_ADD || op == SPL_OP_SUB) {
|
||||
spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected);
|
||||
if (en && en->kind == SPL_LANG_TYPE_PTR) {
|
||||
@@ -765,8 +760,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_lang_type_id_t rt = sema_infer(sema, n->binary.right);
|
||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||
if (!rn || rn->kind != SPL_LANG_TYPE_INT) {
|
||||
SPL_ERROR(&n->dbg, "pointer offset must be integer");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"pointer offset must be integer");
|
||||
return 0;
|
||||
}
|
||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
@@ -809,8 +804,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
usize nelems = vec_size(n->tuple.elems);
|
||||
usize ntypes = vec_size(en->extra.elems);
|
||||
if (nelems != ntypes) {
|
||||
SPL_ERROR(&n->dbg, "tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"tuple arity mismatch (expected %zu, got %zu)", ntypes, nelems);
|
||||
return 0;
|
||||
}
|
||||
for (usize i = 0; i < nelems; ++i) {
|
||||
@@ -830,19 +825,18 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
en->kind != SPL_LANG_TYPE_ENUM))
|
||||
break;
|
||||
|
||||
/* 有名字时,名字必须与 expected 指向同一类型 */
|
||||
if (n->aggregate_literal.name) {
|
||||
spl_symbol_t sym;
|
||||
if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) {
|
||||
SPL_ERROR(&n->dbg, "unknown type `%s`", n->aggregate_literal.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"unknown type `%s`", n->aggregate_literal.name);
|
||||
return 0;
|
||||
}
|
||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||
if (!def || def->lang_id != expected) {
|
||||
SPL_ERROR(&n->dbg, "aggregate `%s` does not match expected type",
|
||||
n->aggregate_literal.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"aggregate `%s` does not match expected type",
|
||||
n->aggregate_literal.name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -850,27 +844,27 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected);
|
||||
spl_type_node_t *irn = spl_type_node(sema->type, agg_ir);
|
||||
if (!irn) {
|
||||
SPL_ERROR(&n->dbg, "aggregate type unresolved");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"aggregate type unresolved");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (en->kind == SPL_LANG_TYPE_ENUM) {
|
||||
if (vec_size(n->aggregate_literal.fields) != 1) {
|
||||
SPL_ERROR(&n->dbg, "enum literal must have exactly one variant");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"enum literal must have exactly one variant");
|
||||
return 0;
|
||||
}
|
||||
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, 0));
|
||||
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) {
|
||||
SPL_ERROR(&n->dbg, "invalid enum literal");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"invalid enum literal");
|
||||
return 0;
|
||||
}
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
||||
SPL_ERROR(&item->dbg, "no variant `%s`", item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`",
|
||||
item->struct_init_item.name);
|
||||
return 0;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
@@ -889,8 +883,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
continue;
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) {
|
||||
SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||
item->struct_init_item.name);
|
||||
continue;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
@@ -924,25 +918,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
return expected;
|
||||
}
|
||||
|
||||
case SPL_AST_EXPR_BLOCK: {
|
||||
sema_push_scope(sema);
|
||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
||||
spl_lang_type_id_t r = 0;
|
||||
if (n->block.tail_expr) {
|
||||
spl_lang_type_id_t t = sema_coerce(sema, n->block.tail_expr, expected);
|
||||
if (!t) {
|
||||
sema_pop_scope(sema);
|
||||
return 0;
|
||||
}
|
||||
r = t;
|
||||
} else {
|
||||
r = spl_lang_make_unit(sema->type);
|
||||
}
|
||||
sema_pop_scope(sema);
|
||||
n->resolved_lang_tid = r;
|
||||
return r;
|
||||
}
|
||||
case SPL_AST_EXPR_BLOCK:
|
||||
return sema_block_body(sema, n, expected);
|
||||
|
||||
default:
|
||||
break;
|
||||
@@ -968,8 +945,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
uint32_t bits = to_ir ? (uint32_t)to_ir->int_type.bits : 0;
|
||||
if (n->kind == SPL_AST_EXPR_INT_LIT && bits != 0 &&
|
||||
!spl_lang_mpa_int_fits(sema->type, expected, n->int_lit)) {
|
||||
SPL_ERROR(&n->dbg, "comptime value does not fit target type");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_FITS_OVERFLOW, &n->dbg,
|
||||
"comptime value does not fit target type");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = expected;
|
||||
@@ -988,8 +965,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
|
||||
char ebuf[128], gbuf[128];
|
||||
sema_type_to_str(sema, expected, ebuf, sizeof(ebuf));
|
||||
sema_type_to_str(sema, from, gbuf, sizeof(gbuf));
|
||||
SPL_ERROR(&n->dbg, "type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"type mismatch: expect %s, got %s (node kind=%d)", ebuf, gbuf, (int)n->kind);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1045,18 +1022,18 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return t;
|
||||
}
|
||||
|
||||
/* ---------- IDENT:同时写 def_id 和 lang_tid 副本 ---------- */
|
||||
/* ---------- IDENT ---------- */
|
||||
case SPL_AST_EXPR_IDENT: {
|
||||
const char *name = n->ident.name;
|
||||
spl_symbol_t sym;
|
||||
if (!spl_scope_find(sema->scope, name, &sym)) {
|
||||
SPL_ERROR(&n->dbg, "undefined identifier `%s`", name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"undefined identifier `%s`", name);
|
||||
return 0;
|
||||
}
|
||||
if (sym.node == 0) {
|
||||
SPL_ERROR(&n->dbg, "identifier `%s` has no definition", name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"identifier `%s` has no definition", name);
|
||||
return 0;
|
||||
}
|
||||
n->resolved_def_id = sym.node;
|
||||
@@ -1077,16 +1054,16 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
switch (n->unary.op) {
|
||||
case SPL_UNARY_OP_MINUS:
|
||||
if (tn->kind != SPL_LANG_TYPE_INT && tn->kind != SPL_LANG_TYPE_FLOAT) {
|
||||
SPL_ERROR(&n->dbg, "unary minus requires numeric operand");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"unary minus requires numeric operand");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = op;
|
||||
return op;
|
||||
case SPL_UNARY_OP_BIT_NOT:
|
||||
if (tn->kind != SPL_LANG_TYPE_INT) {
|
||||
SPL_ERROR(&n->dbg, "bitwise not requires integer operand");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"bitwise not requires integer operand");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = op;
|
||||
@@ -1104,8 +1081,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
case SPL_UNARY_OP_DEREF: {
|
||||
if (tn->kind != SPL_LANG_TYPE_PTR) {
|
||||
SPL_ERROR(&n->dbg, "deref requires pointer operand");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"deref requires pointer operand");
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t elem = tn->extra.elem;
|
||||
@@ -1121,7 +1098,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
case SPL_AST_EXPR_BINARY: {
|
||||
spl_binary_op_t op = n->binary.op;
|
||||
|
||||
/* 赋值 / 复合赋值 */
|
||||
if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
if (!lt)
|
||||
@@ -1131,7 +1107,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return lt;
|
||||
}
|
||||
|
||||
/* 逻辑 */
|
||||
if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) {
|
||||
spl_lang_type_id_t bt = spl_lang_make_bool(sema->type);
|
||||
sema_coerce(sema, n->binary.left, bt);
|
||||
@@ -1152,8 +1127,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"comparison operands type mismatch: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1165,7 +1140,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return b;
|
||||
}
|
||||
|
||||
/* Range */
|
||||
if (op == SPL_OP_RANGE) {
|
||||
sema_infer(sema, n->binary.left);
|
||||
sema_infer(sema, n->binary.right);
|
||||
@@ -1175,15 +1149,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* 移位:结果 = 左类型 */
|
||||
if (op == SPL_OP_LSHIFT || op == SPL_OP_RSHIFT) {
|
||||
spl_lang_type_id_t lt = sema_infer(sema, n->binary.left);
|
||||
if (!lt)
|
||||
return 0;
|
||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||
if (!ln || ln->kind != SPL_LANG_TYPE_INT) {
|
||||
SPL_ERROR(&n->dbg, "shift requires integer operands");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"shift requires integer operands");
|
||||
return 0;
|
||||
}
|
||||
sema_infer(sema, n->binary.right);
|
||||
@@ -1199,9 +1172,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt);
|
||||
spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt);
|
||||
|
||||
/* ptr +/- int 特判:右侧保留自己的整型;
|
||||
* 仅当右操作数是 comptime_int(bits==0)时收紧到 isize,
|
||||
* 避免 comptime 类型泄漏到 IR。 */
|
||||
if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT &&
|
||||
(op == SPL_OP_ADD || op == SPL_OP_SUB)) {
|
||||
spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id);
|
||||
@@ -1218,8 +1188,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
char lbuf[128], rbuf[128];
|
||||
sema_type_to_str(sema, lt, lbuf, sizeof(lbuf));
|
||||
sema_type_to_str(sema, rt, rbuf, sizeof(rbuf));
|
||||
SPL_ERROR(&n->dbg, "operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"operand types cannot be joined: lhs=%s rhs=%s", lbuf, rbuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1245,8 +1215,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_lang_type_id_t callee_tid = sema_infer(sema, n->call.callee);
|
||||
spl_lang_type_node_t *fn = spl_lang_type_node(sema->type, callee_tid);
|
||||
if (!fn || fn->kind != SPL_LANG_TYPE_FN) {
|
||||
SPL_ERROR(&n->dbg, "callee is not a function");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NOT_A_FUNCTION, &n->dbg,
|
||||
"callee is not a function");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1264,15 +1234,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
usize nargs = vec_size(n->call.args);
|
||||
if (has_varargs) {
|
||||
if (nargs < fixed) {
|
||||
SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
|
||||
"too few arguments (expected at least %zu)", fixed);
|
||||
}
|
||||
} else if (nargs != fixed) {
|
||||
SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)", fixed, nargs);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_ARG_COUNT_MISMATCH, &n->dbg,
|
||||
"argument count mismatch (expected %zu, got %zu)", fixed, nargs);
|
||||
}
|
||||
|
||||
/* 固定参数:check 到形参类型 */
|
||||
for (usize i = 0; i < nargs && i < fixed; ++i) {
|
||||
spl_lang_type_id_t pt =
|
||||
vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i);
|
||||
@@ -1311,8 +1280,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
agg_lang = obj->extra.elem;
|
||||
spl_lang_type_node_t *agg = spl_lang_type_node(sema->type, agg_lang);
|
||||
if (!agg) {
|
||||
SPL_ERROR(&n->dbg, "field access on invalid type");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
|
||||
"field access on invalid type");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1322,8 +1291,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
if (m) {
|
||||
spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id);
|
||||
if (!ft) {
|
||||
SPL_ERROR(&n->dbg, "cannot resolve field type");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg,
|
||||
"cannot resolve field type");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = ft;
|
||||
@@ -1341,8 +1310,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
return t;
|
||||
}
|
||||
|
||||
SPL_ERROR(&n->dbg, "no field `%s`", n->field.field);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &n->dbg, "no field `%s`",
|
||||
n->field.field);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1364,22 +1333,22 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
case SPL_LANG_TYPE_TUPLE: {
|
||||
spl_ast_node_t *idx_node = spl_ast_node(sema->ast, n->index.index);
|
||||
if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) {
|
||||
SPL_ERROR(&n->dbg, "tuple index must be an integer literal");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
|
||||
"tuple index must be an integer literal");
|
||||
return 0;
|
||||
}
|
||||
isize i = (isize)idx_node->int_lit.bits;
|
||||
if (i < 0 || (usize)i >= vec_size(obj->extra.elems)) {
|
||||
SPL_ERROR(&n->dbg, "tuple index out of range");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TUPLE_INDEX_OOB, &n->dbg,
|
||||
"tuple index out of range");
|
||||
return 0;
|
||||
}
|
||||
elem = vec_at(obj->extra.elems, (usize)i);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
|
||||
"index base must be array/slice/ptr/range/tuple");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = elem;
|
||||
@@ -1401,8 +1370,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
obj->kind == SPL_LANG_TYPE_SLICE) {
|
||||
elem = obj->extra.elem;
|
||||
} else {
|
||||
SPL_ERROR(&n->dbg, "slice base must be array/ptr/slice");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_INDEX_BASE_INVALID, &n->dbg,
|
||||
"slice base must be array/ptr/slice");
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t s = spl_lang_make_slice(sema->type, elem);
|
||||
@@ -1427,7 +1396,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
sn && sn->kind == SPL_LANG_TYPE_FLOAT && sir && sir->float_type.bits == 0;
|
||||
|
||||
if (src_is_literal_int || src_is_literal_float) {
|
||||
/* 字面量目标物化:允许任意宽度,as 会按其语义处理 */
|
||||
spl_ast_node_t *src_node = spl_ast_node(sema->ast, n->cast.expr);
|
||||
if (src_node && (src_node->kind == SPL_AST_EXPR_INT_LIT ||
|
||||
src_node->kind == SPL_AST_EXPR_FLOAT_LIT)) {
|
||||
@@ -1442,14 +1410,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang);
|
||||
spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang);
|
||||
if (!ft || !tt) {
|
||||
SPL_ERROR(&n->dbg, "as: unresolved source or target type");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||
"as: unresolved source or target type");
|
||||
return 0;
|
||||
}
|
||||
spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt);
|
||||
if (in == SPL_INTRIN_NONE) {
|
||||
SPL_ERROR(&n->dbg, "as: invalid conversion (not supported by as)");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg,
|
||||
"as: invalid conversion (not supported by as)");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = dst_lang;
|
||||
@@ -1509,27 +1477,27 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
spl_symbol_t sym;
|
||||
if (!spl_scope_find(sema->scope, type_name, &sym)) {
|
||||
SPL_ERROR(&n->dbg, "unknown type `%s`", type_name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg, "unknown type `%s`",
|
||||
type_name);
|
||||
return 0;
|
||||
}
|
||||
spl_def_node_t *def = spl_def_node(sema->type, sym.node);
|
||||
if (!def || !def->lang_id) {
|
||||
SPL_ERROR(&n->dbg, "type `%s` not resolved", type_name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"type `%s` not resolved", type_name);
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t agg = def->lang_id;
|
||||
spl_lang_type_node_t *an = spl_lang_type_node(sema->type, agg);
|
||||
if (!an || (an->kind != SPL_LANG_TYPE_STRUCT && an->kind != SPL_LANG_TYPE_UNION &&
|
||||
an->kind != SPL_LANG_TYPE_ENUM)) {
|
||||
SPL_ERROR(&n->dbg, "`%s` is not a struct/union/enum", type_name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"`%s` is not a struct/union/enum", type_name);
|
||||
return 0;
|
||||
}
|
||||
if (an->kind == SPL_LANG_TYPE_ENUM && vec_size(n->aggregate_literal.fields) != 1) {
|
||||
SPL_ERROR(&n->dbg, "enum literal must have exactly one variant");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"enum literal must have exactly one variant");
|
||||
return 0;
|
||||
}
|
||||
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg);
|
||||
@@ -1543,8 +1511,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
usize idx = 0;
|
||||
if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name,
|
||||
&idx)) {
|
||||
SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`",
|
||||
item->struct_init_item.name);
|
||||
continue;
|
||||
}
|
||||
usize field_tid_ir = vec_at(irn->agg_type.variants, idx).type_id;
|
||||
@@ -1561,8 +1529,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
case SPL_AST_EXPR_COMPTIME_CALL: {
|
||||
spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name);
|
||||
if (in == SPL_INTRIN_NONE) {
|
||||
SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg,
|
||||
"unknown comptime call `@%s`", n->comptime_call.name);
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args);
|
||||
@@ -1571,17 +1539,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
|
||||
/* ---------- BLOCK ---------- */
|
||||
case SPL_AST_EXPR_BLOCK: {
|
||||
sema_push_scope(sema);
|
||||
spl_lang_type_id_t last = 0;
|
||||
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
|
||||
sema_infer(sema, vec_at(n->block.stmts, i));
|
||||
if (n->block.tail_expr)
|
||||
last = sema_infer(sema, n->block.tail_expr);
|
||||
sema_pop_scope(sema);
|
||||
n->resolved_lang_tid = last;
|
||||
return last;
|
||||
}
|
||||
case SPL_AST_EXPR_BLOCK:
|
||||
return sema_block_body(sema, n, 0);
|
||||
|
||||
/* ---------- IF ---------- */
|
||||
case SPL_AST_EXPR_IF: {
|
||||
@@ -1666,7 +1625,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg,
|
||||
vec_at(n->for_expr.idents, i));
|
||||
spl_def_resolve(sema->type, sym.node, elem_tid);
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL,
|
||||
&id_node->dbg, "duplicate symbol `%s`", var_name);
|
||||
}
|
||||
id_node->resolved_def_id = sym.node;
|
||||
id_node->resolved_lang_tid = elem_tid;
|
||||
}
|
||||
@@ -1718,8 +1680,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
spl_symbol_t sym;
|
||||
if (!spl_scope_find(sema->scope, name, &sym)) {
|
||||
SPL_ERROR(&n->dbg, "type `%s` not found", name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"type `%s` not found", name);
|
||||
return 0;
|
||||
}
|
||||
spl_lang_type_id_t t = sema_eval_decl(sema, sym.node);
|
||||
@@ -1785,8 +1747,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
const char *name = n->type_comptime_call.name;
|
||||
if (name && strcmp(name, "self") == 0) {
|
||||
if (sema->current_aggregate_lang == 0) {
|
||||
SPL_ERROR(&n->dbg, "`@self` outside of aggregate");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg,
|
||||
"`@self` outside of aggregate");
|
||||
return 0;
|
||||
}
|
||||
n->resolved_lang_tid = sema->current_aggregate_lang;
|
||||
@@ -1842,7 +1804,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
pdef->state = p_tid ? SPL_DECL_RESOLVED : SPL_DECL_ERROR;
|
||||
}
|
||||
pd->resolved_def_id = psym.node;
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, psym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, psym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &pd->dbg,
|
||||
"duplicate symbol `%s`", psym.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
spl_lang_type_id_t old_ret = sema->current_fn_ret_tid;
|
||||
@@ -1885,8 +1850,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
case SPL_AST_CONST_DECL: {
|
||||
spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern);
|
||||
if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) {
|
||||
SPL_ERROR(&n->dbg, "unsupported variable pattern");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg,
|
||||
"unsupported variable pattern");
|
||||
return 0;
|
||||
}
|
||||
const char *name = pat->pattern_ident.name;
|
||||
@@ -1895,7 +1860,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR};
|
||||
sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref);
|
||||
n->resolved_def_id = sym.node;
|
||||
spl_scope_insert(sema->scope, sema->scope->current_scope, sym);
|
||||
if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) {
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg,
|
||||
"duplicate symbol `%s`", name);
|
||||
}
|
||||
}
|
||||
|
||||
spl_lang_type_id_t decl_tid = 0;
|
||||
@@ -1903,8 +1871,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
decl_tid = sema_infer(sema, n->var_const_decl.type);
|
||||
|
||||
if (!n->var_const_decl.init_expr) {
|
||||
SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_VAR_UNINITIALIZED, &n->dbg,
|
||||
"variable `%s` must be initialized", name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1913,8 +1881,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
} else {
|
||||
decl_tid = sema_infer(sema, n->var_const_decl.init_expr);
|
||||
if (!decl_tid || sema_is_infer(sema, decl_tid)) {
|
||||
SPL_ERROR(&n->dbg, "cannot infer type of `%s`", name);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CANNOT_INFER, &n->dbg,
|
||||
"cannot infer type of `%s`", name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1925,16 +1893,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
|
||||
/* ---------- MEMBER / PARAM ---------- */
|
||||
case SPL_AST_MEMBER_DECL: {
|
||||
case SPL_AST_MEMBER_DECL:
|
||||
if (n->member_decl.type_expr)
|
||||
return sema_infer(sema, n->member_decl.type_expr);
|
||||
return 0;
|
||||
}
|
||||
case SPL_AST_PARAM_DECL: {
|
||||
case SPL_AST_PARAM_DECL:
|
||||
if (n->param_decl.type_expr)
|
||||
return sema_infer(sema, n->param_decl.type_expr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------- 语句 ---------- */
|
||||
case SPL_AST_STATEMENT_RET: {
|
||||
@@ -1946,8 +1912,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
} else if (sema->current_fn_ret_tid) {
|
||||
spl_lang_type_id_t u = spl_lang_make_unit(sema->type);
|
||||
if (sema->current_fn_ret_tid != u) {
|
||||
SPL_ERROR(&n->dbg, "function must return a value");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_MUST_RETURN_VALUE, &n->dbg,
|
||||
"function must return a value");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -1960,8 +1926,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
if (vec_size(sema->label_stack) == 0) {
|
||||
SPL_ERROR(&n->dbg, "`break` outside of loop");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_BREAK_OUTSIDE_LOOP, &n->dbg,
|
||||
"`break` outside of loop");
|
||||
return 0;
|
||||
}
|
||||
if (lbl) {
|
||||
@@ -1974,12 +1940,11 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
|
||||
"undefined label `$%s`", lbl);
|
||||
}
|
||||
}
|
||||
if (n->statement_break.expr) {
|
||||
/* 有值 loop:break 值 coerce 到 loop 的期望类型 */
|
||||
if (sema->current_loop_break_tid != 0) {
|
||||
sema_coerce(sema, n->statement_break.expr, sema->current_loop_break_tid);
|
||||
} else {
|
||||
@@ -1996,8 +1961,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
lbl = ln->label.name;
|
||||
}
|
||||
if (vec_size(sema->label_stack) == 0) {
|
||||
SPL_ERROR(&n->dbg, "`continue` outside of loop");
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_CONTINUE_OUTSIDE_LOOP, &n->dbg,
|
||||
"`continue` outside of loop");
|
||||
return 0;
|
||||
}
|
||||
if (lbl) {
|
||||
@@ -2010,8 +1975,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
SPL_ERROR(&n->dbg, "undefined label `$%s`", lbl);
|
||||
sema->error_count++;
|
||||
spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_LABEL, &n->dbg,
|
||||
"undefined label `$%s`", lbl);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -2050,14 +2015,14 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
|
||||
sema->ast = ast;
|
||||
sema->type = type;
|
||||
sema->scope = scope;
|
||||
sema->error_count = 0;
|
||||
sema->current_fn_ret_tid = 0;
|
||||
sema->current_aggregate_lang = 0;
|
||||
sema->current_loop_break_tid = 0;
|
||||
sema->attr = attr;
|
||||
sema->root = (spl_symbol_t){0};
|
||||
sema->store_scope = 0;
|
||||
vec_init(sema->label_stack);
|
||||
|
||||
sema->diag = NULL;
|
||||
}
|
||||
|
||||
void spl_sema_drop(spl_sema_t *sema) { vec_free(sema->label_stack); }
|
||||
|
||||
Reference in new issue
Block a user