stage1 重制类型转换系统 修复问题 提供更多表达式
This commit is contained in:
1 parent
f6a0bce9f0
commit
7cbe2d2b9a
7 files changed
+509
-248
No files matched your search
+93
-20
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user