stage1 重制类型转换系统 修复问题 提供更多表达式

This commit is contained in:
zzy committed 2026-09-16 11:36:29 +08:00
1 parent f6a0bce9f0
commit 7cbe2d2b9a
7 files changed
+509 -248

No files matched your search

+93 -20
View File
@@ -581,7 +581,7 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
switch (in) {
case SPL_INTRIN_SIZEOF:
case SPL_INTRIN_ALIGNOF: {
sema_infer(sema, vec_at(*args, 0)); /* 求类型表达式的值 */
sema_infer(sema, vec_at(*args, 0));
return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
}
case SPL_INTRIN_ASSERT: {
@@ -591,6 +591,48 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n,
sema_infer(sema, vec_at(*args, 1));
return spl_lang_make_unit(sema->type);
}
case SPL_INTRIN_INT_CAST:
case SPL_INTRIN_TRUNCATE:
case SPL_INTRIN_BIT_CAST:
case SPL_INTRIN_FLOAT_CAST:
case SPL_INTRIN_INT_FROM_FLOAT:
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;
spl_lang_type_id_t dst_lang = sema_infer(sema, vec_at(*args, 1));
if (!dst_lang)
return 0;
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);
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++;
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));
if (!dst)
return 0;
n->resolved_lang_tid = dst;
return dst;
}
spl_lang_type_id_t r = spl_lang_make_int(sema->type, sizeof(void *) * 8, 0);
n->resolved_lang_tid = r;
return r;
}
default:
UNREACHABLE();
}
@@ -873,6 +915,15 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref,
return expected;
}
case SPL_AST_EXPR_LOOP: {
spl_lang_type_id_t saved = sema->current_loop_break_tid;
sema->current_loop_break_tid = expected;
sema_infer(sema, ref);
sema->current_loop_break_tid = saved;
n->resolved_lang_tid = expected;
return expected;
}
case SPL_AST_EXPR_BLOCK: {
sema_push_scope(sema);
for (usize i = 0; i < vec_size(n->block.stmts); ++i)
@@ -1361,33 +1412,48 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
/* ---------- CAST ---------- */
case SPL_AST_EXPR_CAST: {
spl_lang_type_id_t dst = sema_infer(sema, n->cast.type);
if (!dst)
spl_lang_type_id_t dst_lang = sema_infer(sema, n->cast.type);
if (!dst_lang)
return 0;
spl_lang_type_id_t src = sema_infer(sema, n->cast.expr);
if (!src)
spl_lang_type_id_t src_lang = sema_infer(sema, n->cast.expr);
if (!src_lang)
return 0;
/* 仅当 src 是 comptime 时收紧到 dst;具体类型间的 as 直接放行(截断/扩展由 ast2ir 生成) */
spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src);
spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src_lang);
spl_type_node_t *sir = sn ? spl_type_node(sema->type, sn->ir_type_id) : NULL;
bool src_comptime =
(sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0) ||
(sn && sn->kind == SPL_LANG_TYPE_FLOAT && sir && sir->float_type.bits == 0);
if (src_comptime) {
if (!sema_coerce(sema, n->cast.expr, dst))
bool src_is_literal_int =
sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0;
bool src_is_literal_float =
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)) {
src_node->resolved_lang_tid = dst_lang;
} else if (!sema_coerce(sema, n->cast.expr, dst_lang)) {
return 0;
}
n->resolved_lang_tid = dst_lang;
return dst_lang;
}
if (sn && !(sn->kind == SPL_LANG_TYPE_INT || sn->kind == SPL_LANG_TYPE_FLOAT ||
sn->kind == SPL_LANG_TYPE_BOOL || sn->kind == SPL_LANG_TYPE_PTR)) {
SPL_ERROR(&n->dbg, "invalid cast from non-primitive type");
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++;
return 0;
}
n->resolved_lang_tid = dst;
return dst;
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++;
return 0;
}
n->resolved_lang_tid = dst_lang;
return dst_lang;
}
/* ---------- TUPLE ---------- */
@@ -1912,8 +1978,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) {
sema->error_count++;
}
}
if (n->statement_break.expr)
sema_infer(sema, n->statement_break.expr);
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 {
sema_infer(sema, n->statement_break.expr);
}
}
return 0;
}
case SPL_AST_STATEMENT_CONTINUE: {
@@ -1981,6 +2053,7 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_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;