stage1 重新实现ast2ir

This commit is contained in:
zzy committed 2026-09-10 23:20:09 +08:00
1 parent bcd26d3021
commit ab6e99c958
10 files changed
+1175 -677

No files matched your search

+225 -163
View File
@@ -62,98 +62,6 @@ static inline void sema_pop_scope(spl_sema_t *sema) {
sema->scope->current_scope = sema->store_scope;
}
static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_lang_type_id_t to,
spl_lang_type_id_t from) {
if (to == 0 || from == 0)
return 0;
spl_lang_type_node_t *to_node = spl_lang_type_node(sema->type, to);
if (!to_node)
return 0;
if (to_node->kind == SPL_LANG_TYPE_INFER)
return from;
spl_lang_type_node_t *from_node = spl_lang_type_node(sema->type, from);
if (!from_node)
return 0;
if (from_node->kind == SPL_LANG_TYPE_INT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(sema->type, from);
spl_type_node_t *from_ir_node = spl_type_node(sema->type, from_ir);
if (from_ir_node && from_ir_node->int_type.bits == 0 && to_node->kind == SPL_LANG_TYPE_INT)
return to;
}
if (from_node->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t from_ir = spl_lang_type_get_ir_type(sema->type, from);
spl_type_node_t *from_ir_node = spl_type_node(sema->type, from_ir);
if (from_ir_node && from_ir_node->float_type.bits == 0 &&
to_node->kind == SPL_LANG_TYPE_FLOAT)
return to;
}
if (to_node->kind == SPL_LANG_TYPE_ARRAY && from_node->kind == SPL_LANG_TYPE_ARRAY) {
spl_lang_type_id_t to_elem = to_node->extra.elem;
spl_lang_type_id_t from_elem = from_node->extra.elem;
if (sema_coerce(sema, to_elem, from_elem) != 0)
return to;
}
if (spl_lang_type_is_subtype(sema->type, from, to))
return to;
return 0;
}
static spl_lang_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_lang_type_id_t t1,
spl_lang_type_id_t t2) {
if (t1 == 0 || t2 == 0)
return 0;
if (t1 == t2)
return t1;
spl_lang_type_node_t *n1 = spl_lang_type_node(sema->type, t1);
spl_lang_type_node_t *n2 = spl_lang_type_node(sema->type, t2);
if (!n1 || !n2)
return 0;
if (n1->kind == SPL_LANG_TYPE_ANY || n2->kind == SPL_LANG_TYPE_ANY)
return spl_lang_make_any(sema->type);
if (n1->kind == SPL_LANG_TYPE_NEVER)
return t2;
if (n2->kind == SPL_LANG_TYPE_NEVER)
return t1;
if (spl_lang_type_is_subtype(sema->type, t1, t2))
return t2;
if (spl_lang_type_is_subtype(sema->type, t2, t1))
return t1;
if (n1->kind == SPL_LANG_TYPE_INT && n2->kind == SPL_LANG_TYPE_INT) {
// 如果一个是另一个的子类型,直接返回父类型(已在前面通用检查中处理)
// 否则符号不同且无法安全提升,返回 0
return 0;
}
if (n1->kind == SPL_LANG_TYPE_FLOAT && n2->kind == SPL_LANG_TYPE_FLOAT) {
spl_type_id_t ir1 = spl_lang_type_get_ir_type(sema->type, t1);
spl_type_id_t ir2 = spl_lang_type_get_ir_type(sema->type, t2);
spl_type_node_t *irn1 = spl_type_node(sema->type, ir1);
spl_type_node_t *irn2 = spl_type_node(sema->type, ir2);
if (irn1 && irn2) {
usize bits = irn1->float_type.bits > irn2->float_type.bits ? irn1->float_type.bits
: irn2->float_type.bits;
return spl_lang_make_float(sema->type, bits);
}
}
return 0;
}
static bool sema_coerce_for_bool(spl_sema_t *sema, spl_lang_type_id_t from) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
return sema_coerce(sema, bool_tid, from) == bool_tid;
}
static spl_lang_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_lang_type_id_t lang_tid) {
spl_lang_type_node_t *n = spl_lang_type_node(sema->type, lang_tid);
if (!n)
@@ -176,18 +84,29 @@ static void sema_collect(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;
spl_symbol_t file_sym = {.name = "$file", .kind = SPL_SYMBOL_KIND_TYPE};
file_sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, ref);
n->resolved_def_id = file_sym.node;
spl_scope_id_t root_scope = spl_scope_alloc(sema->scope);
sema->scope->current_scope = root_scope;
sema->scope->root_scope = root_scope;
spl_scope_insert(sema->scope, root_scope, file_sym);
spl_scope_insert(sema->scope, mod_scope, file_sym);
for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) {
sema_collect(sema, vec_at(n->container_members.declarations, i));
}
/* 故意不恢复 current_scope
保持 mod_scope 交给随后的 sema_parse 使用。
恢复由 spl_sema_run_module 统一负责 */
break;
}
case SPL_AST_TYPE_DECL: {
@@ -417,15 +336,19 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
return 0;
}
spl_ast_node_t *init_node = spl_ast_node(sema->ast, n->var_const_decl.init_expr);
spl_lang_type_id_t init_tid = sema_parse(sema, n->var_const_decl.init_expr);
decl_tid = sema_coerce(sema, decl_tid, init_tid);
if (decl_tid == 0) {
SPL_ERROR(&n->dbg, "cannot infer type for variable `%s`", name);
spl_lang_type_id_t coerce_result = spl_lang_type_coerce_to(sema->type, decl_tid, init_tid);
if (coerce_result == 0) {
SPL_ERROR(&n->dbg, "cannot coerce initializer to declared type");
sema->error_count++;
return 0;
}
init_node->resolved_type_id = coerce_result;
decl_tid = coerce_result;
spl_def_resolve(sema->type, n->resolved_def_id, decl_tid);
n->resolved_type_id = decl_tid; // 存储 lang_id
n->resolved_type_id = decl_tid;
return decl_tid;
}
@@ -500,6 +423,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
sema->error_count++;
return 0;
}
n->resolved_type_id = def->lang_id;
return def->lang_id;
}
@@ -556,14 +480,18 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
spl_binary_op_t op = n->binary.op;
switch (op) {
case SPL_OP_ASSIGN:
if (sema_coerce(sema, lt, rt) == 0) {
case SPL_OP_ASSIGN: {
spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt);
if (r == 0) {
SPL_ERROR(&n->dbg, "assignment type mismatch");
sema->error_count++;
return 0;
}
rhs->resolved_type_id = r;
n->resolved_type_id = lt;
return lt;
}
case SPL_OP_ASSIGN_ADD:
case SPL_OP_ASSIGN_SUB:
@@ -575,12 +503,20 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_ASSIGN_XOR:
case SPL_OP_ASSIGN_LSHIFT:
case SPL_OP_ASSIGN_RSHIFT: {
spl_lang_type_id_t balanced = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t balanced = spl_lang_type_balance(sema->type, lt, rt);
if (balanced == 0 || balanced != lt) {
SPL_ERROR(&n->dbg, "compound assignment type mismatch");
sema->error_count++;
return 0;
}
spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt);
if (r == 0) {
SPL_ERROR(&n->dbg, "compound assignment right type mismatch");
sema->error_count++;
return 0;
}
rhs->resolved_type_id = r;
n->resolved_type_id = lt;
return lt;
}
@@ -602,13 +538,22 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_BIT_OR:
case SPL_OP_BIT_XOR:
case SPL_OP_BIT_AND: {
spl_lang_type_id_t bal = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt);
spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal);
if (!bn || bn->kind != SPL_LANG_TYPE_INT) {
SPL_ERROR(&n->dbg, "bitwise operands must be integers");
sema->error_count++;
return 0;
}
/* 两边都 coerce 到 bal */
if (lt != bal) {
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left);
ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt);
}
if (rt != bal) {
spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right);
rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt);
}
n->resolved_type_id = bal;
return bal;
}
@@ -619,13 +564,12 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_CMP_GE:
case SPL_OP_CMP_LT:
case SPL_OP_CMP_GT: {
// FIXME 不一定合理
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);
bool numeric =
(ln && (ln->kind == SPL_LANG_TYPE_INT || ln->kind == SPL_LANG_TYPE_FLOAT)) &&
(rn && (rn->kind == SPL_LANG_TYPE_INT || rn->kind == SPL_LANG_TYPE_FLOAT));
if (!numeric && sema_coerce_balance(sema, lt, rt) == 0) {
if (!numeric && spl_lang_type_balance(sema->type, lt, rt) == 0) {
SPL_ERROR(&n->dbg, "comparison operands type mismatch");
sema->error_count++;
return 0;
@@ -653,13 +597,21 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_OP_MUL:
case SPL_OP_DIV:
case SPL_OP_MOD: {
spl_lang_type_id_t bal = sema_coerce_balance(sema, lt, rt);
spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt);
spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal);
if (!bn || (bn->kind != SPL_LANG_TYPE_INT && bn->kind != SPL_LANG_TYPE_FLOAT)) {
SPL_ERROR(&n->dbg, "arithmetic operands type mismatch");
sema->error_count++;
return 0;
}
if (lt != bal) {
spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left);
ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt);
}
if (rt != bal) {
spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right);
rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt);
}
n->resolved_type_id = bal;
return bal;
}
@@ -699,35 +651,41 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
if (has_varargs) {
// 可变参数函数:实参数量至少等于固定参数数量
if (vec_size(n->call.args) < fixed_param_count) {
SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed_param_count);
sema->error_count++;
} else {
// 检查固定参数部分
for (usize i = 0; i < fixed_param_count; ++i) {
spl_lang_type_id_t arg_tid = sema_parse(sema, vec_at(n->call.args, i));
spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i);
spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref);
spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref);
spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i);
if (sema_coerce(sema, param_tid, arg_tid) == 0) {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1);
sema->error_count++;
} else {
arg_node->resolved_type_id = r;
}
}
// 额外参数不进行类型检查(或可扩展为元组类型检查)
}
} else {
// 非可变参数函数:实参数量必须严格匹配
if (vec_size(n->call.args) != vec_size(fn->extra.fn.params)) {
SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)",
vec_size(fn->extra.fn.params), vec_size(n->call.args));
sema->error_count++;
} else {
for (usize i = 0; i < vec_size(n->call.args); ++i) {
spl_lang_type_id_t arg_tid = sema_parse(sema, vec_at(n->call.args, i));
spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i);
spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref);
spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref);
spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i);
if (sema_coerce(sema, param_tid, arg_tid) == 0) {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1);
sema->error_count++;
} else {
arg_node->resolved_type_id = r;
}
}
}
@@ -880,56 +838,68 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
case SPL_AST_EXPR_ARRAY_LIT: {
/* elem_type 可空:匿名 .[...] 时从元素推导 */
spl_lang_type_id_t elem_tid = 0;
if (n->array_literal.elem_type) {
elem_tid = sema_parse(sema, n->array_literal.elem_type);
}
for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) {
spl_lang_type_id_t et = sema_parse(sema, vec_at(n->array_literal.elems, i));
if (elem_tid == 0)
spl_ast_node_ref_t elem_ref = vec_at(n->array_literal.elems, i);
spl_ast_node_t *elem_node = spl_ast_node(sema->ast, elem_ref);
spl_lang_type_id_t et = sema_parse(sema, elem_ref);
if (elem_tid == 0) {
elem_tid = et;
else if (sema_coerce(sema, elem_tid, et) == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
sema->error_count++;
} else {
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, elem_tid, et);
if (r == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
sema->error_count++;
} else {
elem_node->resolved_type_id = r;
}
}
}
if (elem_tid == 0) {
SPL_ERROR(&n->dbg, "cannot infer array element type "
"(empty literal without element type annotation)");
sema->error_count++;
return 0;
}
usize len;
if (n->array_literal.is_underscore_len) {
len = vec_size(n->array_literal.elems);
} else {
len =
n->array_literal.has_len ? n->array_literal.len : vec_size(n->array_literal.elems);
}
spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len);
n->resolved_type_id = arr_tid;
return arr_tid;
}
case SPL_AST_EXPR_ANON_ARRAY_LIT: {
spl_lang_type_id_t elem_tid = 0;
for (usize i = 0; i < vec_size(n->anon_array_literal.elems); ++i) {
spl_lang_type_id_t et = sema_parse(sema, vec_at(n->anon_array_literal.elems, i));
if (elem_tid == 0)
elem_tid = et;
else if (sema_coerce(sema, elem_tid, et) == 0) {
SPL_ERROR(&n->dbg, "array element type mismatch");
} else if (n->array_literal.has_len) {
len = (usize)n->array_literal.len;
if (len != vec_size(n->array_literal.elems)) {
SPL_ERROR(&n->dbg, "array literal length mismatch: declared %zu, got %zu", len,
vec_size(n->array_literal.elems));
sema->error_count++;
}
} else {
len = vec_size(n->array_literal.elems);
}
usize len = vec_size(n->anon_array_literal.elems);
spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len);
n->resolved_type_id = arr_tid;
return arr_tid;
}
case SPL_AST_EXPR_AGGREGATE_LIT: {
const char *type_name = n->aggregate_literal.name;
/* 匿名 .{...}:需要类型上下文。
SEMA 当前为自底向上,尚无"预期类型"传播机制;
待上层注解散布到 init_expr 之前时启用。
结构上已统一,只需在这里读取 n->resolved_type_id 即可。 */
if (!type_name) {
SPL_ERROR(&n->dbg, "anonymous aggregate literal not supported yet");
SPL_ERROR(&n->dbg, "anonymous aggregate literal requires expected type context "
"(not yet supported)");
sema->error_count++;
return 0;
}
spl_symbol_t sym;
if (!spl_scope_find(sema->scope, type_name, &sym)) {
SPL_ERROR(&n->dbg, "unknown type `%s`", type_name);
@@ -952,23 +922,44 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang);
spl_type_node_t *agg_ir_node = spl_type_node(sema->type, agg_ir);
if (!agg_ir_node) {
SPL_ERROR(&n->dbg, "aggregate IR type `%s` not found", type_name);
sema->error_count++;
return 0;
}
usize total_fields = vec_size(agg_ir_node->agg_type.variants);
/* 记录每个字段是否被初始化,最后检查缺省 */
bool *seen = calloc(total_fields, sizeof(bool));
if (!seen) {
SPL_ERROR(&n->dbg, "out of memory");
sema->error_count++;
return 0;
}
for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) {
spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i));
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
continue;
const char *fname = item->struct_init_item.name;
spl_lang_type_id_t field_lang = 0;
if (item->struct_init_item.expr) {
field_lang = sema_parse(sema, item->struct_init_item.expr);
}
const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_ir, fname);
if (!member) {
usize field_idx = 0;
if (!spl_type_agg_member_idx(sema->type, agg_ir, fname, &field_idx)) {
SPL_ERROR(&item->dbg, "no field `%s` in `%s`", fname, type_name);
sema->error_count++;
continue;
}
// 映射到底层类型对应的语言级类型
if (seen[field_idx]) {
SPL_ERROR(&item->dbg, "duplicate field `%s` in `%s`", fname, type_name);
sema->error_count++;
continue;
}
seen[field_idx] = true;
const spl_type_member_t *member = &vec_at(agg_ir_node->agg_type.variants, field_idx);
/* 通过字段的 ir 类型反查 lang 类型 */
spl_lang_type_id_t expected_lang = 0;
for (usize j = 1; j < vec_size(sema->type->lang_table); ++j) {
spl_lang_type_node_t *ln = &vec_at(sema->type->lang_table, j);
@@ -978,15 +969,37 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
}
}
if (!expected_lang) {
SPL_ERROR(&item->dbg, "cannot resolve field type for `%s`", fname);
SPL_ERROR(&item->dbg, "cannot resolve lang type for field `%s`", fname);
sema->error_count++;
continue;
}
if (sema_coerce(sema, expected_lang, field_lang) == 0) {
if (!item->struct_init_item.expr) {
SPL_ERROR(&item->dbg, "field `%s` requires an initializer", fname);
sema->error_count++;
continue;
}
spl_ast_node_t *fv = spl_ast_node(sema->ast, item->struct_init_item.expr);
spl_lang_type_id_t field_lang = sema_parse(sema, item->struct_init_item.expr);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected_lang, field_lang);
if (r == 0) {
SPL_ERROR(&item->dbg, "field `%s` type mismatch", fname);
sema->error_count++;
} else {
fv->resolved_type_id = r;
}
}
/* 检查缺省字段 */
for (usize i = 0; i < total_fields; ++i) {
if (!seen[i]) {
const spl_type_member_t *m = &vec_at(agg_ir_node->agg_type.variants, i);
SPL_ERROR(&n->dbg, "missing field `%s` in `%s`", m->name, type_name);
sema->error_count++;
}
}
free(seen);
n->resolved_type_id = agg_lang;
return agg_lang;
@@ -1007,15 +1020,43 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_EXPR_IF: {
spl_lang_type_id_t cond_tid = sema_parse(sema, n->if_expr.cond);
if (!sema_coerce_for_bool(sema, cond_tid)) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) {
SPL_ERROR(&n->dbg, "if condition must be bool");
sema->error_count++;
}
sema_parse(sema, n->if_expr.then_block);
if (n->if_expr.else_branch) {
sema_parse(sema, n->if_expr.else_branch);
spl_lang_type_id_t then_t =
n->if_expr.then_block ? sema_parse(sema, n->if_expr.then_block) : 0;
spl_lang_type_id_t else_t =
n->if_expr.else_branch ? sema_parse(sema, n->if_expr.else_branch) : 0;
spl_lang_type_id_t result_t = 0;
if (then_t && else_t) {
result_t = spl_lang_type_balance(sema->type, then_t, else_t);
if (result_t == 0) {
SPL_ERROR(&n->dbg, "if branches type mismatch");
sema->error_count++;
} else {
if (then_t != result_t) {
spl_ast_node_t *tn = spl_ast_node(sema->ast, n->if_expr.then_block);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, then_t);
if (r)
tn->resolved_type_id = r;
}
if (else_t != result_t) {
spl_ast_node_t *en = spl_ast_node(sema->ast, n->if_expr.else_branch);
spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, else_t);
if (r)
en->resolved_type_id = r;
}
}
} else {
result_t = then_t ? then_t : else_t;
}
return 0;
n->resolved_type_id = result_t;
return result_t;
}
case SPL_AST_EXPR_IFVAR: {
@@ -1029,7 +1070,8 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_EXPR_WHILE: {
spl_lang_type_id_t cond_tid = sema_parse(sema, n->while_expr.cond);
if (!sema_coerce_for_bool(sema, cond_tid)) {
spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type);
if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) {
SPL_ERROR(&n->dbg, "while condition must be bool");
sema->error_count++;
}
@@ -1189,16 +1231,21 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) {
case SPL_AST_STATEMENT_RET: {
if (n->statement_ret.expr) {
spl_ast_node_t *en = spl_ast_node(sema->ast, n->statement_ret.expr);
spl_lang_type_id_t ret_tid = sema_parse(sema, n->statement_ret.expr);
if (sema->current_fn_ret_tid != 0 &&
sema_coerce(sema, sema->current_fn_ret_tid, ret_tid) == 0) {
SPL_ERROR(&n->dbg, "return type mismatch");
sema->error_count++;
if (sema->current_fn_ret_tid != 0) {
spl_lang_type_id_t r =
spl_lang_type_coerce_to(sema->type, sema->current_fn_ret_tid, ret_tid);
if (r == 0) {
SPL_ERROR(&n->dbg, "return type mismatch");
sema->error_count++;
} else {
en->resolved_type_id = r;
}
}
}
return 0;
}
case SPL_AST_STATEMENT_BREAK:
case SPL_AST_STATEMENT_CONTINUE:
return 0;
@@ -1245,6 +1292,22 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope
void spl_sema_drop(spl_sema_t *sema) { (void)sema; }
void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) {
if (!sema->ast || !module_ref)
return;
spl_ast_node_t *mod = spl_ast_node(sema->ast, module_ref);
if (!mod || mod->kind != SPL_AST_CONTAINER_MEMBERS)
return;
spl_scope_id_t saved = sema->scope->current_scope;
sema_collect(sema, module_ref);
/* 此时 current_scope == 该 module 的 mod_scope */
sema_parse(sema, module_ref);
sema->scope->current_scope = saved;
}
void spl_sema_run(spl_sema_t *sema) {
if (!sema->ast || !sema->ast->root)
return;
@@ -1253,8 +1316,7 @@ void spl_sema_run(spl_sema_t *sema) {
if (!root || root->kind != SPL_AST_ROOT)
return;
sema_collect(sema, root->root.members);
sema_parse(sema, root->root.members);
spl_sema_run_module(sema, root->root.members);
}
void spl_sema_dump(spl_sema_t *sema) {