diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index f1db83a..8476125 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -349,13 +349,13 @@ static void parse_param_list(parser_t *p, spl_ast_node_ref_vec_t *out) { if (peek(p) && peek(p)->type == TOK_COMMA) advance(p); break; - } else if (t->type == KW_VOID) { - advance(p); - t = peek(p); - if (!t || t->type != TOK_R_PAREN) { - SPL_FATAL(t, "expected ')' after void"); - } - break; + // } else if (t->type == KW_VOID) { + // advance(p); + // t = peek(p); + // if (!t || t->type != TOK_R_PAREN) { + // SPL_FATAL(t, "expected ')' after void"); + // } + // break; } else { SPL_FATAL(t, "unexpected token in parameter list"); break; @@ -849,9 +849,10 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) { (len == 5 && strncmp(name, "usize", 5) == 0) || (len == 3 && strncmp(name, "f32", 3) == 0) || (len == 3 && strncmp(name, "f64", 3) == 0) || - (len == 4 && strncmp(name, "bool", 4) == 0) || - (len == 4 && strncmp(name, "void", 4) == 0) || - (len == 3 && strncmp(name, "ptr", 3) == 0)) { + (len == 4 && strncmp(name, "bool", 4) == 0) + // (len == 4 && strncmp(name, "void", 4) == 0) || + // (len == 3 && strncmp(name, "any", 3) == 0) + ) { advance(p); spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt); spl_ast_node_t *tp = node_at(p->ast, ref); @@ -886,6 +887,16 @@ static spl_ast_node_ref_t parse_type_base(parser_t *p) { return parse_type_comptime_call(p); } + if (bt->type == KW_ANY) { + advance(p); + spl_ast_node_ref_t ref = new_node(p, SPL_AST_TYPE_PATH, bt); + spl_ast_node_t *tp = node_at(p->ast, ref); + SET_STR_FIELD(p->ast, tp->type_path.name, bt); + vec_init(tp->type_path.generic_args); + vec_free(tag_list); + return ref; + } + vec_free(tag_list); SPL_FATAL(bt, "unrecognized type"); return 0; diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index ce928b2..e0ba4cc 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -354,7 +354,7 @@ struct spl_ast_node { struct { bool has_len; - isize len; + usize len; bool is_underscore_len; spl_ast_node_ref_t elem_type; spl_ast_node_ref_vec_t elems; diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 95ac674..08989e3 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -1,4 +1,5 @@ #include "spl_sema.h" +#include "spl_type.h" void spl_scope_init(spl_scope_t *scope) { vec_init(scope->scopes); @@ -45,7 +46,6 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { 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)) { - Assert(out->kind != SPL_SYMBOL_KIND_ERROR); return true; } } @@ -62,105 +62,110 @@ static inline void sema_pop_scope(spl_sema_t *sema) { sema->scope->current_scope = sema->store_scope; } -static spl_type_id_t sema_coerce(spl_sema_t *sema, spl_type_id_t to, spl_type_id_t from) { +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_type_node_t *to_node = spl_type_node(sema->type, to); - // 目标类型是待推断,直接采用源类型 - if (to_node && to_node->lang_kind == SPL_LANG_TYPE_INFER) { - return from; - } - - spl_type_node_t *from_node = spl_type_node(sema->type, from); - if (!to_node || !from_node) + spl_lang_type_node_t *to_node = spl_lang_type_node(sema->type, to); + if (!to_node) return 0; - // 源类型为未指定数值(bits==0)时,根据目标类型具体化 - if (from_node->kind == SPL_TYPE_INT && from_node->int_type.bits == 0) { - if (to_node->kind == SPL_TYPE_INT) { + 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; - } - } else if (from_node->kind == SPL_TYPE_FLOAT && from_node->float_type.bits == 0) { - if (to_node->kind == SPL_TYPE_FLOAT) { + } + 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; - } } - // 数组协变:若目标与源都是数组,且元素类型能 coerce,则返回目标数组类型 - if (to_node->kind == SPL_TYPE_ARRAY && from_node->kind == SPL_TYPE_ARRAY) { - spl_type_id_t to_elem = to_node->array_type.element; - spl_type_id_t from_elem = from_node->array_type.element; - if (sema_coerce(sema, to_elem, from_elem) != 0) { + 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_type_is_subtype(sema->type, from, to)) { + if (spl_lang_type_is_subtype(sema->type, from, to)) return to; - } + return 0; } -static spl_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_type_id_t t1, spl_type_id_t t2) { +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_type_node_t *n1 = spl_type_node(sema->type, t1); - spl_type_node_t *n2 = spl_type_node(sema->type, t2); + 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; - // 处理 ANY(top) - if (n1->kind == SPL_TYPE_ANY || n2->kind == SPL_TYPE_ANY) - return spl_type_make_any(sema->type); - - // 处理 NEVER(bottom) - if (n1->kind == SPL_TYPE_NEVER) + 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_TYPE_NEVER) + if (n2->kind == SPL_LANG_TYPE_NEVER) return t1; - // 其余逻辑保持原样,但最好改为使用子类型判断 - if (spl_type_is_subtype(sema->type, t1, t2)) + if (spl_lang_type_is_subtype(sema->type, t1, t2)) return t2; - if (spl_type_is_subtype(sema->type, t2, t1)) + 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_type_id_t from) { - spl_type_id_t bool_tid = spl_type_make_bool(sema->type); +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_type_id_t sema_for_elem_type(spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *n = spl_type_node(sema->type, 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) return 0; - switch (n->lang_kind) { - case SPL_LANG_TYPE_SLICE: { - const spl_type_member_t *ptr_member = spl_type_agg_member(sema->type, tid, "ptr"); - if (!ptr_member) - return 0; - spl_type_node_t *ptr_node = spl_type_node(sema->type, ptr_member->type_id); - if (!ptr_node || ptr_node->kind != SPL_TYPE_PTR) - return 0; - return ptr_node->ptr_type.pointee; - } + switch (n->kind) { + case SPL_LANG_TYPE_ARRAY: + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + case SPL_LANG_TYPE_PTR: + return n->extra.elem; default: - switch (n->kind) { - case SPL_TYPE_ARRAY: - return n->array_type.element; - case SPL_TYPE_PTR: - return n->ptr_type.pointee; - default: - return 0; - } + return 0; } } @@ -246,7 +251,7 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } -static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { +static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (ref == 0) return 0; spl_ast_node_t *n = spl_ast_node(sema->ast, ref); @@ -265,19 +270,23 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { Panic("fn `%s` not collected", n->fn_decl.name); } - spl_type_id_vec_t param_types; + spl_lang_type_id_vec_t param_types; vec_init(param_types); for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i)); if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr) { vec_push(param_types, sema_parse(sema, pd->param_decl.type_expr)); } else { - vec_push(param_types, 0); + vec_push(param_types, spl_lang_make_varargs(sema->type)); } } - spl_type_id_t ret_tid = sema_parse(sema, n->fn_decl.ret_type); - spl_type_id_t fn_tid = spl_type_make_fn( + spl_lang_type_id_t ret_tid = sema_parse(sema, n->fn_decl.ret_type); + if (ret_tid == 0) { + ret_tid = spl_lang_make_unit(sema->type); + } + spl_lang_type_id_t fn_tid = spl_lang_make_fn( sema->type, ret_tid, vec_unsafe_get_data(param_types), vec_size(param_types)); + Assert(fn_tid != 0); vec_free(param_types); spl_def_resolve(sema->type, n->resolved_def_id, fn_tid); @@ -289,13 +298,13 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR}; psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg, vec_at(n->fn_decl.params, i)); - spl_type_id_t p_tid = sema_parse(sema, pd->param_decl.type_expr); + spl_lang_type_id_t p_tid = sema_parse(sema, pd->param_decl.type_expr); spl_def_resolve(sema->type, psym.node, p_tid); pd->resolved_def_id = psym.node; spl_scope_insert(sema->scope, sema->scope->current_scope, psym); } } - spl_type_id_t old_ret = sema->current_fn_ret_tid; + spl_lang_type_id_t old_ret = sema->current_fn_ret_tid; sema->current_fn_ret_tid = ret_tid; sema_parse(sema, n->fn_decl.body); sema->current_fn_ret_tid = old_ret; @@ -317,9 +326,9 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { spl_ast_node_t *mn = spl_ast_node(sema->ast, vec_at(te->type_aggregate.members, i)); if (mn && mn->kind == SPL_AST_MEMBER_DECL) { - spl_type_id_t mtid = sema_parse(sema, mn->member_decl.type_expr); + spl_lang_type_id_t mtid = sema_parse(sema, mn->member_decl.type_expr); spl_type_member_t m = {.name = mn->member_decl.name, - .type_id = mtid, + .type_id = spl_lang_type_get_ir_type(sema->type, mtid), .ast_node_ref = vec_at(te->type_aggregate.members, i)}; vec_push(members, m); } @@ -336,12 +345,33 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { tk = SPL_TYPE_STRUCT; spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO}; - spl_type_id_t agg_tid = spl_type_make_agg( - sema->type, tk, &members, - spl_type_make_int(sema->type, 32, 1), // 默认索引类型 i32 TODO check i32 - layout); + spl_type_id_t agg_ir = spl_type_builder_agg( + sema->type, tk, &members, spl_type_builder_int(sema->type, 32, 1), layout); vec_free(members); - spl_def_resolve(sema->type, n->resolved_def_id, agg_tid); + + // 创建语言级节点 + spl_lang_type_node_t lang_node = {0}; + switch (tk) { + case SPL_TYPE_STRUCT: + lang_node.kind = SPL_LANG_TYPE_STRUCT; + break; + case SPL_TYPE_UNION: + lang_node.kind = SPL_LANG_TYPE_UNION; + break; + case SPL_TYPE_ENUM: + lang_node.kind = SPL_LANG_TYPE_ENUM; + break; + case SPL_TYPE_SHAPE: + lang_node.kind = SPL_LANG_TYPE_SHAPE; + break; + default: + break; + } + lang_node.ir_type_id = agg_ir; + vec_push(sema->type->lang_table, lang_node); + spl_lang_type_id_t agg_lang = vec_size(sema->type->lang_table) - 1; + spl_def_resolve(sema->type, n->resolved_def_id, agg_lang); + n->resolved_type_id = agg_lang; // 存储 lang_id // 处理聚合内部的函数声明 for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { @@ -351,9 +381,9 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } } else { - // 标量类型别名,仍然使用 def_resolve 关联已有类型 - spl_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); + spl_lang_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); spl_def_resolve(sema->type, n->resolved_def_id, tid); + n->resolved_type_id = tid; // 存储 lang_id } break; } @@ -375,11 +405,11 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_scope_insert(sema->scope, sema->scope->current_scope, sym); } - spl_type_id_t decl_tid; + spl_lang_type_id_t decl_tid; if (n->var_const_decl.type) { decl_tid = sema_parse(sema, n->var_const_decl.type); } else { - decl_tid = spl_type_make_infer(sema->type); + decl_tid = spl_lang_make_infer(sema->type); } if (n->var_const_decl.init_expr == 0) { SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name); @@ -387,7 +417,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } - spl_type_id_t init_tid = sema_parse(sema, 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); @@ -395,6 +425,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } spl_def_resolve(sema->type, n->resolved_def_id, decl_tid); + n->resolved_type_id = decl_tid; // 存储 lang_id return decl_tid; } @@ -413,38 +444,39 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_INT_LIT: { - spl_type_id_t ct = spl_type_make_int(sema->type, 0, true); + spl_lang_type_id_t ct = spl_lang_make_int(sema->type, 0, 1); n->resolved_type_id = ct; return ct; } case SPL_AST_EXPR_FLOAT_LIT: { - spl_type_id_t ct = spl_type_make_float(sema->type, 0); + spl_lang_type_id_t ct = spl_lang_make_float(sema->type, 0); n->resolved_type_id = ct; return ct; } case SPL_AST_EXPR_CHAR_LIT: { - spl_type_id_t u8 = spl_type_make_int(sema->type, 8, false); + spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); n->resolved_type_id = u8; return u8; } case SPL_AST_EXPR_STRING_LIT: { - spl_type_id_t u8_tid = spl_type_make_int(sema->type, 8, false); - spl_type_id_t slice_tid = spl_type_make_slice(sema->type, u8_tid); - n->resolved_type_id = slice_tid; - return slice_tid; + spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); + spl_lang_type_id_t slice = spl_lang_make_slice(sema->type, u8); + n->resolved_type_id = slice; + return slice; } case SPL_AST_EXPR_BOOL_LIT: { - spl_type_id_t bt = spl_type_make_bool(sema->type); + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); n->resolved_type_id = bt; return bt; } case SPL_AST_EXPR_NULL_LIT: { - spl_type_id_t t = spl_type_make_ptr(sema->type, spl_type_make_never(sema->type)); - n->resolved_type_id = t; - return t; + spl_lang_type_id_t never = spl_lang_make_never(sema->type); + spl_lang_type_id_t ptr = spl_lang_make_ptr(sema->type, never); + n->resolved_type_id = ptr; + return ptr; } case SPL_AST_EXPR_UNDEFINED_LIT: { - spl_type_id_t t = spl_type_make_never(sema->type); + spl_lang_type_id_t t = spl_lang_make_never(sema->type); n->resolved_type_id = t; return t; } @@ -468,20 +500,20 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - return def->type_id; + return def->lang_id; } case SPL_AST_EXPR_UNARY: { - spl_type_id_t operand_tid = sema_parse(sema, n->unary.operand); + spl_lang_type_id_t operand_tid = sema_parse(sema, n->unary.operand); if (operand_tid == 0) return 0; - spl_type_node_t *tn = spl_type_node(sema->type, operand_tid); + spl_lang_type_node_t *tn = spl_lang_type_node(sema->type, operand_tid); if (!tn) return 0; switch (n->unary.op) { case SPL_UNARY_OP_MINUS: - if (tn->kind != SPL_TYPE_INT && tn->kind != SPL_TYPE_FLOAT) { + 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++; return 0; @@ -489,18 +521,18 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { n->resolved_type_id = operand_tid; return operand_tid; case SPL_UNARY_OP_NOT: - if (tn->kind != SPL_TYPE_BOOL) { + if (tn->kind != SPL_LANG_TYPE_BOOL) { SPL_ERROR(&n->dbg, "logical not requires bool operand"); sema->error_count++; return 0; } { - spl_type_id_t bt = spl_type_make_bool(sema->type); + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); n->resolved_type_id = bt; return bt; } case SPL_UNARY_OP_BIT_NOT: - if (tn->kind != SPL_TYPE_INT) { + if (tn->kind != SPL_LANG_TYPE_INT) { SPL_ERROR(&n->dbg, "bitwise not requires integer operand"); sema->error_count++; return 0; @@ -508,7 +540,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { n->resolved_type_id = operand_tid; return operand_tid; case SPL_UNARY_OP_ADDRESS: { - spl_type_id_t ptr_tid = spl_type_make_ptr(sema->type, operand_tid); + spl_lang_type_id_t ptr_tid = spl_lang_make_ptr(sema->type, operand_tid); n->resolved_type_id = ptr_tid; return ptr_tid; } @@ -519,8 +551,8 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_BINARY: { - spl_type_id_t lt = sema_parse(sema, n->binary.left); - spl_type_id_t rt = sema_parse(sema, n->binary.right); + spl_lang_type_id_t lt = sema_parse(sema, n->binary.left); + spl_lang_type_id_t rt = sema_parse(sema, n->binary.right); spl_binary_op_t op = n->binary.op; switch (op) { @@ -543,7 +575,7 @@ static spl_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_type_id_t balanced = sema_coerce_balance(sema, lt, rt); + spl_lang_type_id_t balanced = sema_coerce_balance(sema, lt, rt); if (balanced == 0 || balanced != lt) { SPL_ERROR(&n->dbg, "compound assignment type mismatch"); sema->error_count++; @@ -555,14 +587,14 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_OP_BOOL_OR: case SPL_OP_BOOL_AND: { - spl_type_node_t *ln = spl_type_node(sema->type, lt); - spl_type_node_t *rn = spl_type_node(sema->type, rt); - if (!ln || ln->kind != SPL_TYPE_BOOL || !rn || rn->kind != SPL_TYPE_BOOL) { + 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); + if (!ln || ln->kind != SPL_LANG_TYPE_BOOL || !rn || rn->kind != SPL_LANG_TYPE_BOOL) { SPL_ERROR(&n->dbg, "logical operands must be bool"); sema->error_count++; return 0; } - spl_type_id_t bt = spl_type_make_bool(sema->type); + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); n->resolved_type_id = bt; return bt; } @@ -570,9 +602,9 @@ static spl_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_type_id_t bal = sema_coerce_balance(sema, lt, rt); - spl_type_node_t *bn = spl_type_node(sema->type, bal); - if (!bn || bn->kind != SPL_TYPE_INT) { + spl_lang_type_id_t bal = sema_coerce_balance(sema, 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; @@ -587,21 +619,27 @@ static spl_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: { - if (sema_coerce_balance(sema, lt, rt) == 0) { + // 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) { SPL_ERROR(&n->dbg, "comparison operands type mismatch"); sema->error_count++; return 0; } - spl_type_id_t bt = spl_type_make_bool(sema->type); + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); n->resolved_type_id = bt; return bt; } case SPL_OP_LSHIFT: case SPL_OP_RSHIFT: { - spl_type_node_t *ln = spl_type_node(sema->type, lt); - spl_type_node_t *rn = spl_type_node(sema->type, rt); - if (!ln || ln->kind != SPL_TYPE_INT || !rn || rn->kind != SPL_TYPE_INT) { + 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); + if (!ln || ln->kind != SPL_LANG_TYPE_INT || !rn || rn->kind != SPL_LANG_TYPE_INT) { SPL_ERROR(&n->dbg, "shift operands must be integers"); sema->error_count++; return 0; @@ -615,9 +653,9 @@ static spl_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_type_id_t bal = sema_coerce_balance(sema, lt, rt); - spl_type_node_t *bn = spl_type_node(sema->type, bal); - if (!bn || (bn->kind != SPL_TYPE_INT && bn->kind != SPL_TYPE_FLOAT)) { + spl_lang_type_id_t bal = sema_coerce_balance(sema, 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; @@ -627,9 +665,10 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_OP_RANGE: { - spl_type_id_t i64 = spl_type_make_int(sema->type, 64, true); - n->resolved_type_id = i64; - return i64; + spl_lang_type_id_t i64 = spl_lang_make_int(sema->type, 64, 1); + spl_lang_type_id_t range = spl_lang_make_range(sema->type, i64); + n->resolved_type_id = range; + return range; } default: @@ -639,156 +678,186 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_CALL: { - spl_type_id_t callee_tid = sema_parse(sema, n->call.callee); - spl_type_node_t *fn = spl_type_node(sema->type, callee_tid); - if (!fn || fn->kind != SPL_TYPE_FN) { + spl_lang_type_id_t callee_tid = sema_parse(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++; return 0; } - if (vec_size(n->call.args) != vec_size(fn->fn_type.params)) { - SPL_ERROR(&n->dbg, "argument count mismatch"); - sema->error_count++; + + // 检查函数是否可变参数:最后一个参数是否为 VARARGS + bool has_varargs = false; + usize fixed_param_count = vec_size(fn->extra.fn.params); + if (fixed_param_count > 0) { + spl_lang_type_id_t last_param = vec_at(fn->extra.fn.params, fixed_param_count - 1); + spl_lang_type_node_t *last_node = spl_lang_type_node(sema->type, last_param); + if (last_node && last_node->kind == SPL_LANG_TYPE_VARARGS) { + has_varargs = true; + fixed_param_count--; // 排除 VARARGS 参数 + } + } + + 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_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i); + if (sema_coerce(sema, param_tid, arg_tid) == 0) { + SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); + sema->error_count++; + } + } + // 额外参数不进行类型检查(或可扩展为元组类型检查) + } } else { - for (usize i = 0; i < vec_size(n->call.args); ++i) { - spl_type_id_t arg_tid = sema_parse(sema, vec_at(n->call.args, i)); - spl_type_id_t param_tid = vec_at(fn->fn_type.params, i); - if (sema_coerce(sema, param_tid, arg_tid) == 0) { - SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); - sema->error_count++; + // 非可变参数函数:实参数量必须严格匹配 + 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_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i); + if (sema_coerce(sema, param_tid, arg_tid) == 0) { + SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); + sema->error_count++; + } } } } - spl_type_id_t ret_tid = fn->fn_type.ret; + + spl_lang_type_id_t ret_tid = fn->extra.fn.ret; n->resolved_type_id = ret_tid; return ret_tid; } case SPL_AST_EXPR_FIELD: { - spl_type_id_t obj_tid = sema_parse(sema, n->field.obj); - spl_type_node_t *obj_node = spl_type_node(sema->type, obj_tid); + spl_lang_type_id_t obj_tid = sema_parse(sema, n->field.obj); + spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); if (!obj_node) return 0; - spl_type_id_t agg_tid = obj_tid; - if (obj_node->kind == SPL_TYPE_PTR) { - agg_tid = obj_node->ptr_type.pointee; + // 内建字段:数组/切片的 len + if ((obj_node->kind == SPL_LANG_TYPE_ARRAY || obj_node->kind == SPL_LANG_TYPE_SLICE) && + strcmp(n->field.field, "len") == 0) { + spl_lang_type_id_t usize_tid = spl_lang_make_int(sema->type, sizeof(void *) * 8, 0); + n->resolved_type_id = usize_tid; + return usize_tid; } - spl_type_node_t *agg_node = spl_type_node(sema->type, agg_tid); - if (!agg_node || (agg_node->kind != SPL_TYPE_STRUCT && agg_node->kind != SPL_TYPE_UNION)) { + + // 自动解引用 + spl_lang_type_id_t agg_lang = obj_tid; + if (obj_node->kind == SPL_LANG_TYPE_PTR) { + agg_lang = obj_node->extra.elem; + } + spl_lang_type_node_t *agg_node = spl_lang_type_node(sema->type, agg_lang); + if (!agg_node || + (agg_node->kind != SPL_LANG_TYPE_STRUCT && agg_node->kind != SPL_LANG_TYPE_UNION)) { SPL_ERROR(&n->dbg, "field access on non-aggregate type"); sema->error_count++; return 0; } - const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_tid, n->field.field); + spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); + const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_ir, n->field.field); if (!member) { SPL_ERROR(&n->dbg, "no field `%s`", n->field.field); sema->error_count++; return 0; } - n->resolved_type_id = member->type_id; - return member->type_id; + + // 将底层字段类型映射回语言级类型 + spl_lang_type_id_t field_lang = 0; + for (usize i = 1; i < vec_size(sema->type->lang_table); ++i) { + spl_lang_type_node_t *ln = &vec_at(sema->type->lang_table, i); + if (ln->ir_type_id == member->type_id) { + field_lang = i; + break; + } + } + if (!field_lang) { + SPL_ERROR(&n->dbg, "cannot resolve field type for `%s`", n->field.field); + sema->error_count++; + return 0; + } + n->resolved_type_id = field_lang; + return field_lang; } case SPL_AST_EXPR_INDEX: { - spl_type_id_t obj_tid = sema_parse(sema, n->index.obj); - spl_type_id_t idx_tid = sema_parse(sema, n->index.index); - spl_type_node_t *obj_node = spl_type_node(sema->type, obj_tid); + spl_lang_type_id_t obj_tid = sema_parse(sema, n->index.obj); + spl_lang_type_id_t idx_tid = sema_parse(sema, n->index.index); + spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); if (!obj_node) return 0; - spl_type_id_t elem_tid = 0; - switch (obj_node->lang_kind) { - case SPL_LANG_TYPE_SLICE: { - const spl_type_member_t *ptr_member = spl_type_agg_member(sema->type, obj_tid, "ptr"); - if (!ptr_member) { - SPL_ERROR(&n->dbg, "slice missing ptr member"); - sema->error_count++; - return 0; - } - spl_type_node_t *ptr_node = spl_type_node(sema->type, ptr_member->type_id); - if (!ptr_node || ptr_node->kind != SPL_TYPE_PTR) { - SPL_ERROR(&n->dbg, "slice ptr member not pointer"); - sema->error_count++; - return 0; - } - elem_tid = ptr_node->ptr_type.pointee; + spl_lang_type_id_t elem_lang = 0; + switch (obj_node->kind) { + case SPL_LANG_TYPE_ARRAY: + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + case SPL_LANG_TYPE_PTR: + elem_lang = obj_node->extra.elem; break; - } - case SPL_LANG_TYPE_TUPLE: { - // 对于元组索引,需要常量索引,暂简化为返回第一个成员类型 - if (vec_size(obj_node->agg_type.variants) > 0) - elem_tid = vec_at(obj_node->agg_type.variants, 0).type_id; + case SPL_LANG_TYPE_TUPLE: + if (vec_size(obj_node->extra.elems) > 0) + elem_lang = vec_at(obj_node->extra.elems, 0); else { SPL_ERROR(&n->dbg, "empty tuple"); sema->error_count++; return 0; } break; - } default: - switch (obj_node->kind) { - case SPL_TYPE_ARRAY: - elem_tid = obj_node->array_type.element; - break; - case SPL_TYPE_PTR: - elem_tid = obj_node->ptr_type.pointee; - break; - default: - SPL_ERROR(&n->dbg, "index base must be array, pointer, slice, or tuple"); - sema->error_count++; - return 0; - } - break; + SPL_ERROR(&n->dbg, "index base must be array, pointer, slice, or tuple"); + sema->error_count++; + return 0; } (void)idx_tid; - n->resolved_type_id = elem_tid; - return elem_tid; + n->resolved_type_id = elem_lang; + return elem_lang; } case SPL_AST_EXPR_SLICE: { - spl_type_id_t obj_tid = sema_parse(sema, n->slice.obj); + spl_lang_type_id_t obj_tid = sema_parse(sema, n->slice.obj); if (n->slice.begin) sema_parse(sema, n->slice.begin); if (n->slice.end) sema_parse(sema, n->slice.end); - spl_type_node_t *obj_node = spl_type_node(sema->type, obj_tid); + spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); if (!obj_node) return 0; - spl_type_id_t elem_tid = 0; - if (obj_node->kind == SPL_TYPE_ARRAY) { - elem_tid = obj_node->array_type.element; - } else if (obj_node->kind == SPL_TYPE_PTR) { - elem_tid = obj_node->ptr_type.pointee; - } else if (obj_node->lang_kind == SPL_LANG_TYPE_SLICE) { - // 对 slice 再切片,元素类型保持不变 - const spl_type_member_t *ptr_member = spl_type_agg_member(sema->type, obj_tid, "ptr"); - if (ptr_member) { - spl_type_node_t *ptr_node = spl_type_node(sema->type, ptr_member->type_id); - if (ptr_node && ptr_node->kind == SPL_TYPE_PTR) - elem_tid = ptr_node->ptr_type.pointee; - } + spl_lang_type_id_t elem_lang = 0; + if (obj_node->kind == SPL_LANG_TYPE_ARRAY || obj_node->kind == SPL_LANG_TYPE_PTR || + obj_node->kind == SPL_LANG_TYPE_SLICE) { + elem_lang = obj_node->extra.elem; } else { SPL_ERROR(&n->dbg, "slice base must be array, pointer, or slice"); sema->error_count++; return 0; } - spl_type_id_t slice_tid = spl_type_make_slice(sema->type, elem_tid); + spl_lang_type_id_t slice_tid = spl_lang_make_slice(sema->type, elem_lang); n->resolved_type_id = slice_tid; return slice_tid; } case SPL_AST_EXPR_CAST: { - spl_type_id_t src_tid = sema_parse(sema, n->cast.expr); - spl_type_id_t dst_tid = sema_parse(sema, n->cast.type); - spl_type_node_t *src_node = spl_type_node(sema->type, src_tid); + spl_lang_type_id_t src_tid = sema_parse(sema, n->cast.expr); + spl_lang_type_id_t dst_tid = sema_parse(sema, n->cast.type); + spl_lang_type_node_t *src_node = spl_lang_type_node(sema->type, src_tid); if (!src_node) return 0; - if (src_node->kind != SPL_TYPE_INT && src_node->kind != SPL_TYPE_FLOAT && - src_node->kind != SPL_TYPE_BOOL) { + if (src_node->kind != SPL_LANG_TYPE_INT && src_node->kind != SPL_LANG_TYPE_FLOAT && + src_node->kind != SPL_LANG_TYPE_BOOL) { SPL_ERROR(&n->dbg, "invalid cast from non-primitive type"); sema->error_count++; return 0; @@ -798,19 +867,25 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_TUPLE: { + spl_lang_type_id_vec_t elems; + vec_init(elems); for (usize i = 0; i < vec_size(n->tuple.elems); ++i) { - sema_parse(sema, vec_at(n->tuple.elems, i)); + vec_push(elems, sema_parse(sema, vec_at(n->tuple.elems, i))); } - return 0; + spl_lang_type_id_t tuple = + spl_lang_make_tuple(sema->type, vec_unsafe_get_data(elems), vec_size(elems)); + vec_free(elems); + n->resolved_type_id = tuple; + return tuple; } case SPL_AST_EXPR_ARRAY_LIT: { - spl_type_id_t elem_tid = 0; + 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_type_id_t et = sema_parse(sema, vec_at(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) elem_tid = et; else if (sema_coerce(sema, elem_tid, et) == 0) { @@ -826,15 +901,15 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { len = n->array_literal.has_len ? n->array_literal.len : vec_size(n->array_literal.elems); } - spl_type_id_t arr_tid = spl_type_make_array(sema->type, elem_tid, len); + 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_type_id_t elem_tid = 0; + spl_lang_type_id_t elem_tid = 0; for (usize i = 0; i < vec_size(n->anon_array_literal.elems); ++i) { - spl_type_id_t et = sema_parse(sema, vec_at(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) { @@ -843,7 +918,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } usize len = vec_size(n->anon_array_literal.elems); - spl_type_id_t arr_tid = spl_type_make_array(sema->type, elem_tid, len); + 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; } @@ -862,38 +937,59 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } spl_def_node_t *def = spl_def_node(sema->type, sym.node); - spl_type_id_t tid = def ? def->type_id : 0; - spl_type_node_t *tn = spl_type_node(sema->type, tid); - if (!tn || (tn->kind != SPL_TYPE_STRUCT && tn->kind != SPL_TYPE_UNION)) { + if (!def || !def->lang_id) { + SPL_ERROR(&n->dbg, "type `%s` not resolved", type_name); + sema->error_count++; + return 0; + } + spl_lang_type_id_t agg_lang = def->lang_id; + spl_lang_type_node_t *agg_node = spl_lang_type_node(sema->type, agg_lang); + if (!agg_node || + (agg_node->kind != SPL_LANG_TYPE_STRUCT && agg_node->kind != SPL_LANG_TYPE_UNION)) { SPL_ERROR(&n->dbg, "`%s` is not a struct/union", type_name); sema->error_count++; return 0; } + spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); 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_type_id_t field_tid = 0; + spl_lang_type_id_t field_lang = 0; if (item->struct_init_item.expr) { - field_tid = sema_parse(sema, 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, tid, fname); + const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_ir, fname); if (!member) { SPL_ERROR(&item->dbg, "no field `%s` in `%s`", fname, type_name); sema->error_count++; continue; } - if (sema_coerce(sema, member->type_id, field_tid) == 0) { + // 映射到底层类型对应的语言级类型 + 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); + if (ln->ir_type_id == member->type_id) { + expected_lang = j; + break; + } + } + if (!expected_lang) { + SPL_ERROR(&item->dbg, "cannot resolve field type for `%s`", fname); + sema->error_count++; + continue; + } + if (sema_coerce(sema, expected_lang, field_lang) == 0) { SPL_ERROR(&item->dbg, "field `%s` type mismatch", fname); sema->error_count++; } } - n->resolved_type_id = tid; - return tid; + n->resolved_type_id = agg_lang; + return agg_lang; } case SPL_AST_EXPR_COMPTIME_CALL: @@ -910,7 +1006,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_IF: { - spl_type_id_t cond_tid = sema_parse(sema, n->if_expr.cond); + spl_lang_type_id_t cond_tid = sema_parse(sema, n->if_expr.cond); if (!sema_coerce_for_bool(sema, cond_tid)) { SPL_ERROR(&n->dbg, "if condition must be bool"); sema->error_count++; @@ -932,7 +1028,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_WHILE: { - spl_type_id_t cond_tid = sema_parse(sema, n->while_expr.cond); + spl_lang_type_id_t cond_tid = sema_parse(sema, n->while_expr.cond); if (!sema_coerce_for_bool(sema, cond_tid)) { SPL_ERROR(&n->dbg, "while condition must be bool"); sema->error_count++; @@ -952,8 +1048,8 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_EXPR_FOR: { sema_push_scope(sema); for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) { - spl_type_id_t container_tid = sema_parse(sema, vec_at(n->for_expr.iter_exprs, i)); - spl_type_id_t elem_tid = sema_for_elem_type(sema, container_tid); + spl_lang_type_id_t container_tid = sema_parse(sema, vec_at(n->for_expr.iter_exprs, i)); + spl_lang_type_id_t elem_tid = sema_for_elem_type(sema, container_tid); if (i < vec_size(n->for_expr.idents)) { spl_ast_node_t *id_node = spl_ast_node(sema->ast, vec_at(n->for_expr.idents, i)); if (id_node && id_node->kind == SPL_AST_EXPR_IDENT) { @@ -990,14 +1086,14 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } case SPL_AST_EXPR_FN_TYPE: { - spl_type_id_vec_t params; + spl_lang_type_id_vec_t params; vec_init(params); for (usize i = 0; i < vec_size(n->fn_type.params); ++i) { vec_push(params, sema_parse(sema, vec_at(n->fn_type.params, i))); } - spl_type_id_t ret_tid = sema_parse(sema, n->fn_type.ret_type); - spl_type_id_t fn_tid = - spl_type_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); + spl_lang_type_id_t ret_tid = sema_parse(sema, n->fn_type.ret_type); + spl_lang_type_id_t fn_tid = + spl_lang_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); vec_free(params); n->resolved_type_id = fn_tid; return fn_tid; @@ -1006,14 +1102,12 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_TYPE_PATH: { const char *name = n->type_path.name; - // 先询问 type 模块是否为内建类型 - spl_type_id_t builtin = spl_type_lookup_builtin(sema->type, name); + spl_lang_type_id_t builtin = spl_type_lookup_builtin(sema->type, name); if (builtin != 0) { n->resolved_type_id = builtin; return builtin; } - // 否则查找用户定义类型 spl_symbol_t sym; if (!spl_scope_find(sema->scope, name, &sym)) { SPL_ERROR(&n->dbg, "type `%s` not found", name); @@ -1021,43 +1115,43 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } spl_def_node_t *def = spl_def_node(sema->type, sym.node); - if (!def) + if (!def || !def->lang_id) return 0; - n->resolved_type_id = def->type_id; - return def->type_id; + n->resolved_type_id = def->lang_id; + return def->lang_id; } case SPL_AST_TYPE_POINTER: { - spl_type_id_t pointee_tid = sema_parse(sema, n->type_pointer.pointee); - spl_type_id_t ptr_tid = spl_type_make_ptr(sema->type, pointee_tid); + spl_lang_type_id_t pointee_tid = sema_parse(sema, n->type_pointer.pointee); + spl_lang_type_id_t ptr_tid = spl_lang_make_ptr(sema->type, pointee_tid); n->resolved_type_id = ptr_tid; return ptr_tid; } case SPL_AST_TYPE_ARRAY: { - spl_type_id_t elem_tid = sema_parse(sema, n->type_array.elem_type); + spl_lang_type_id_t elem_tid = sema_parse(sema, n->type_array.elem_type); usize len = n->type_array.has_len ? (usize)n->type_array.len : 0; - spl_type_id_t arr_tid = spl_type_make_array(sema->type, elem_tid, len); + 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_TYPE_SLICE: { - spl_type_id_t elem_tid = sema_parse(sema, n->type_slice.elem_type); - spl_type_id_t slice_tid = spl_type_make_slice(sema->type, elem_tid); + spl_lang_type_id_t elem_tid = sema_parse(sema, n->type_slice.elem_type); + spl_lang_type_id_t slice_tid = spl_lang_make_slice(sema->type, elem_tid); n->resolved_type_id = slice_tid; return slice_tid; } case SPL_AST_TYPE_FN: { - spl_type_id_vec_t params; + spl_lang_type_id_vec_t params; vec_init(params); for (usize i = 0; i < vec_size(n->type_fn.params); ++i) { vec_push(params, sema_parse(sema, vec_at(n->type_fn.params, i))); } - spl_type_id_t ret_tid = sema_parse(sema, n->type_fn.ret_type); - spl_type_id_t fn_tid = - spl_type_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); + spl_lang_type_id_t ret_tid = sema_parse(sema, n->type_fn.ret_type); + spl_lang_type_id_t fn_tid = + spl_lang_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); vec_free(params); n->resolved_type_id = fn_tid; return fn_tid; @@ -1066,7 +1160,7 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_TYPE_PAREN: { usize count = vec_size(n->type_paren.types); if (count == 0) { - spl_type_id_t unit = spl_type_make_unit(sema->type); + spl_lang_type_id_t unit = spl_lang_make_unit(sema->type); n->resolved_type_id = unit; return unit; } @@ -1074,19 +1168,16 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return sema_parse(sema, vec_at(n->type_paren.types, 0)); } - spl_type_member_vec_t members; - vec_init(members); - char name_buf[32]; // TODO string builder + spl_lang_type_id_vec_t elems; + vec_init(elems); for (usize i = 0; i < count; ++i) { - spl_type_id_t tid = sema_parse(sema, vec_at(n->type_paren.types, i)); - snprintf(name_buf, sizeof(name_buf), "%zu", i); - spl_type_member_t m = {.name = strdup(name_buf), .type_id = tid, .ast_node_ref = 0}; - vec_push(members, m); + vec_push(elems, sema_parse(sema, vec_at(n->type_paren.types, i))); } - spl_type_id_t tuple_tid = spl_type_make_tuple(sema->type, &members); - vec_free(members); - n->resolved_type_id = tuple_tid; - return tuple_tid; + spl_lang_type_id_t tuple = + spl_lang_make_tuple(sema->type, vec_unsafe_get_data(elems), vec_size(elems)); + vec_free(elems); + n->resolved_type_id = tuple; + return tuple; } case SPL_AST_TYPE_AGGREGATE: { @@ -1098,7 +1189,7 @@ static spl_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_type_id_t ret_tid = sema_parse(sema, 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"); @@ -1143,7 +1234,6 @@ static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope) { - Assert(sema && ast && type && scope); sema->ast = ast; sema->type = type; sema->scope = scope; @@ -1160,9 +1250,8 @@ void spl_sema_run(spl_sema_t *sema) { return; spl_ast_node_t *root = spl_ast_node(sema->ast, sema->ast->root); - Assert(root && root->kind == SPL_AST_ROOT); - spl_ast_node_t *container = spl_ast_node(sema->ast, root->root.members); - Assert(container && container->kind == SPL_AST_CONTAINER_MEMBERS); + if (!root || root->kind != SPL_AST_ROOT) + return; sema_collect(sema, root->root.members); sema_parse(sema, root->root.members); @@ -1170,9 +1259,7 @@ void spl_sema_run(spl_sema_t *sema) { void spl_sema_dump(spl_sema_t *sema) { printf("Scopes:\n"); - for (usize i = 0; i < vec_size(sema->scope->scopes); ++i) { - if (i == 0) - continue; + for (usize i = 1; i < vec_size(sema->scope->scopes); ++i) { spl_scope_node_t *scope = &vec_at(sema->scope->scopes, i); printf("scope[%zu] parent=%zu\n", i, scope->parent); map_for(scope->symbols, j) { @@ -1181,16 +1268,22 @@ void spl_sema_dump(spl_sema_t *sema) { symbol->node); } } + printf("LangTypeTable:\n"); + for (usize i = 1; i < vec_size(sema->type->lang_table); ++i) { + printf(" lang_id#%zu ", i); + spl_lang_type_dump(sema->type, i); + printf("\n"); + } printf("TypeTable:\n"); - for (usize i = 0; i < vec_size(sema->type->type_table); ++i) { - printf(" id#%zu ", i); + for (usize i = 1; i < vec_size(sema->type->type_table); ++i) { + printf(" type_id#%zu ", i); spl_type_pure_dump(sema->type, i); printf("\n"); } printf("DefTable:\n"); - for (usize i = 0; i < vec_size(sema->type->def_table); ++i) { + for (usize i = 1; i < vec_size(sema->type->def_table); ++i) { printf(" def#%zu ", i); spl_type_def_dump(sema->type, i); printf("\n"); } -} \ No newline at end of file +} diff --git a/stage1/spl_tok.h b/stage1/spl_tok.h index 104d7cb..5c53d73 100644 --- a/stage1/spl_tok.h +++ b/stage1/spl_tok.h @@ -6,6 +6,7 @@ /* clang-format off */ #define KEYWORD_TABLE \ + X(any , KW_ANY , SPL_V0) \ X(as , KW_AS , SPL_V0) \ X(bool , KW_BOOL , SPL_V0) \ X(break , KW_BREAK , SPL_V0) \ @@ -33,7 +34,6 @@ X(undefined , KW_UNDEFINED , SPL_V0) \ X(union , KW_UNION , SPL_V0) \ X(var , KW_VAR , SPL_V0) \ - X(void , KW_VOID , SPL_V0) \ X(while , KW_WHILE , SPL_V0) \ X(_ , KW_UNDERSCORE , SPL_V0) \ // KEYWORD_TABLE diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 239b86f..2f72d59 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -1,7 +1,7 @@ #include "spl_type.h" static usize spl_type_hash(spl_type_node_t n) { - usize hash = n.kind << 20; // FIXME least i32 + usize hash = (usize)n.kind * 131; switch (n.kind) { case SPL_TYPE_ERROR: case SPL_TYPE_UNIT: @@ -13,7 +13,7 @@ static usize spl_type_hash(spl_type_node_t n) { case SPL_TYPE_BOOL: break; case SPL_TYPE_INT: - hash += n.int_type.bits + n.int_type.is_signed; + hash += n.int_type.bits + (usize)n.int_type.is_signed; break; case SPL_TYPE_FLOAT: hash += n.float_type.bits; @@ -28,18 +28,24 @@ static usize spl_type_hash(spl_type_node_t n) { case SPL_TYPE_UNION: case SPL_TYPE_ENUM: case SPL_TYPE_SHAPE: - hash += n.layout.mode * 31 + n.layout.fixed_align_bits; + hash += (usize)n.layout.mode * 31 + n.layout.fixed_align_bits; hash += n.agg_type.tag_type; - vec_for(n.agg_type.variants, i) { - hash += - (n.agg_type.variants.data[i].name ? map_hash_str(n.agg_type.variants.data[i].name) - : 0) + - n.agg_type.variants.data[i].type_id; + for (usize i = 0; i < vec_size(n.agg_type.variants); i++) { + spl_type_member_t *m = &n.agg_type.variants.data[i]; + hash += m->type_id; + if (m->name) { + const char *s = m->name; + while (*s) { + hash = hash * 31 + (usize)(*s++); + } + } } break; case SPL_TYPE_FN: hash += n.fn_type.ret; - vec_for(n.fn_type.params, i) { hash += vec_at(n.fn_type.params, i); } + for (usize i = 0; i < vec_size(n.fn_type.params); i++) { + hash += vec_at(n.fn_type.params, i); + } break; } return hash; @@ -57,27 +63,17 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { case SPL_TYPE_FORALL: case SPL_TYPE_EXISTS: case SPL_TYPE_BOOL: - break; + return 0; case SPL_TYPE_INT: - if (n1.int_type.bits != n2.int_type.bits) - return 1; - if (n1.int_type.is_signed != n2.int_type.is_signed) - return 1; - break; + return (n1.int_type.bits != n2.int_type.bits) || + (n1.int_type.is_signed != n2.int_type.is_signed); case SPL_TYPE_FLOAT: - if (n1.float_type.bits != n2.float_type.bits) - return 1; - break; + return n1.float_type.bits != n2.float_type.bits; case SPL_TYPE_PTR: - if (n1.ptr_type.pointee != n2.ptr_type.pointee) - return 1; - break; + return n1.ptr_type.pointee != n2.ptr_type.pointee; case SPL_TYPE_ARRAY: - if (n1.array_type.element != n2.array_type.element) - return 1; - if (n1.array_type.len != n2.array_type.len) - return 1; - break; + return (n1.array_type.element != n2.array_type.element) || + (n1.array_type.len != n2.array_type.len); case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: case SPL_TYPE_ENUM: @@ -89,31 +85,32 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; if (vec_size(n1.agg_type.variants) != vec_size(n2.agg_type.variants)) return 1; - vec_for(n1.agg_type.variants, i) { - const char *na = n1.agg_type.variants.data[i].name; - const char *nb = n2.agg_type.variants.data[i].name; - if (strcmp(na ? na : "", nb ? nb : "") != 0) + for (usize i = 0; i < vec_size(n1.agg_type.variants); i++) { + spl_type_member_t *a = &n1.agg_type.variants.data[i]; + spl_type_member_t *b = &n2.agg_type.variants.data[i]; + if (a->type_id != b->type_id) return 1; - if (n1.agg_type.variants.data[i].type_id != n2.agg_type.variants.data[i].type_id) + if ((a->name == NULL) != (b->name == NULL)) + return 1; + if (a->name && strcmp(a->name, b->name) != 0) return 1; } - break; + return 0; case SPL_TYPE_FN: if (n1.fn_type.ret != n2.fn_type.ret) return 1; if (vec_size(n1.fn_type.params) != vec_size(n2.fn_type.params)) return 1; - vec_for(n1.fn_type.params, i) { + for (usize i = 0; i < vec_size(n1.fn_type.params); i++) { if (vec_at(n1.fn_type.params, i) != vec_at(n2.fn_type.params, i)) return 1; } - break; + return 0; } - return 0; + return 1; } static usize spl_type_map_hash(usize k) { return MAP_HASH_INT(k); } - static int spl_type_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } static void spl_type_node_free_vecs(spl_type_node_t *tn) { @@ -146,10 +143,152 @@ spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *tn) { spl_type_id_t id = vec_size(type->type_table); vec_push(type->type_table, *tn); map_put_new(type->type_map, hash, id); + // 清空传入节点中的动态成员,防止重复释放 tn->kind = SPL_TYPE_ERROR; return id; } +static usize spl_lang_type_hash(spl_lang_type_node_t n) { + usize hash = (usize)n.kind * 131 + n.ir_type_id; + switch (n.kind) { + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + hash += n.extra.elem; + break; + case SPL_LANG_TYPE_TUPLE: + for (usize i = 0; i < vec_size(n.extra.elems); i++) { + hash += vec_at(n.extra.elems, i); + } + break; + case SPL_LANG_TYPE_FN: + hash += n.extra.fn.ret; + for (usize i = 0; i < vec_size(n.extra.fn.params); i++) { + hash += vec_at(n.extra.fn.params, i); + } + break; + default: + break; + } + return hash; +} + +static int spl_lang_type_eq(spl_lang_type_node_t n1, spl_lang_type_node_t n2) { + if (n1.kind != n2.kind || n1.ir_type_id != n2.ir_type_id) + return 1; + switch (n1.kind) { + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + return n1.extra.elem != n2.extra.elem; + case SPL_LANG_TYPE_TUPLE: + if (vec_size(n1.extra.elems) != vec_size(n2.extra.elems)) + return 1; + for (usize i = 0; i < vec_size(n1.extra.elems); i++) { + if (vec_at(n1.extra.elems, i) != vec_at(n2.extra.elems, i)) + return 1; + } + return 0; + case SPL_LANG_TYPE_FN: + if (n1.extra.fn.ret != n2.extra.fn.ret) + return 1; + if (vec_size(n1.extra.fn.params) != vec_size(n2.extra.fn.params)) + return 1; + for (usize i = 0; i < vec_size(n1.extra.fn.params); i++) { + if (vec_at(n1.extra.fn.params, i) != vec_at(n2.extra.fn.params, i)) + return 1; + } + return 0; + default: + return 0; + } +} + +static usize spl_lang_map_hash(usize k) { return MAP_HASH_INT(k); } +static int spl_lang_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } + +static void spl_lang_node_free_extra(spl_lang_type_node_t *n) { + switch (n->kind) { + case SPL_LANG_TYPE_TUPLE: + vec_free(n->extra.elems); + break; + case SPL_LANG_TYPE_FN: + vec_free(n->extra.fn.params); + break; + default: + break; + } +} + +static spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node) { + usize hash = spl_lang_type_hash(*node); + usize idx = (usize)-1; + spl_lang_type_id_t cand = 0; + while (map_get_continue(type->lang_map, hash, &cand, &idx)) { + spl_lang_type_node_t *existing = &vec_at(type->lang_table, cand); + if (spl_lang_type_eq(*existing, *node) == 0) { + spl_lang_node_free_extra(node); + return cand; + } + } + spl_lang_type_id_t id = vec_size(type->lang_table); + vec_push(type->lang_table, *node); + map_put_new(type->lang_map, hash, id); + node->kind = SPL_LANG_TYPE_ERROR; + return id; +} + +void spl_type_init(spl_type_t *type) { + vec_init(type->type_table); + spl_type_node_t type_node = {0}; + vec_push(type->type_table, type_node); + map_init(type->type_map, spl_type_map_hash, spl_type_map_cmp); + + vec_init(type->lang_table); + spl_lang_type_node_t lang_type_node = {0}; + vec_push(type->lang_table, lang_type_node); + map_init(type->lang_map, spl_lang_map_hash, spl_lang_map_cmp); + + vec_init(type->def_table); + vec_push(type->def_table, (spl_def_node_t){0}); +} + +void spl_type_drop(spl_type_t *type) { + // 释放底层类型 + for (usize i = 0; i < vec_size(type->type_table); i++) { + spl_type_node_t *n = &vec_at(type->type_table, i); + spl_type_node_free_vecs(n); + } + map_free(type->type_map); + vec_free(type->type_table); + + // 释放语言级类型 + for (usize i = 0; i < vec_size(type->lang_table); i++) { + spl_lang_type_node_t *n = &vec_at(type->lang_table, i); + spl_lang_node_free_extra(n); + } + map_free(type->lang_map); + vec_free(type->lang_table); + + vec_free(type->def_table); +} + +spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id) { + if (!id || id >= vec_size(type->type_table)) + return NULL; + return &vec_at(type->type_table, id); +} + +spl_lang_type_node_t *spl_lang_type_node(const spl_type_t *type, spl_lang_type_id_t id) { + if (!id || id >= vec_size(type->lang_table)) + return NULL; + return &vec_at(type->lang_table, id); +} + +spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id) { + if (!id || id >= vec_size(type->def_table)) + return NULL; + return &vec_at(type->def_table, id); +} + bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super) { if (sub == 0 || super == 0) return false; @@ -161,49 +300,122 @@ bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_ if (!nsub || !nsuper) return false; - // never 是任何类型的子类型 bottom + // never 是任何类型的子类型 if (nsub->kind == SPL_TYPE_NEVER) return true; - // 任何类型是 any 的子类型 top + // 任何类型是 any 的子类型 if (nsuper->kind == SPL_TYPE_ANY) return true; - // 处理 comptime_int / comptime_float 到具体数值类型 + // 数值类型子类型:comptime_int (bits=0) 可适配任何整数 if (nsub->kind == SPL_TYPE_INT && nsuper->kind == SPL_TYPE_INT) { - if (nsub->int_type.is_signed != nsuper->int_type.is_signed) - return false; - // comptime_int bits==0 可适配任何整数 if (nsub->int_type.bits == 0) - return true; - return nsub->int_type.bits <= nsuper->int_type.bits; + return true; // comptime_int 适配任意整数 + if (nsub->int_type.is_signed == nsuper->int_type.is_signed) { + return nsub->int_type.bits <= nsuper->int_type.bits; + } + // 无符号 → 有符号:目标位数必须大于源位数(需要额外符号位) + if (!nsub->int_type.is_signed && nsuper->int_type.is_signed) { + return nsuper->int_type.bits > nsub->int_type.bits; + } + // 有符号 → 无符号:不允许 + return false; } - if (nsub->kind == SPL_TYPE_FLOAT && nsuper->kind == SPL_TYPE_FLOAT) { - // comptime_float bits==0 可适配任何浮点 if (nsub->float_type.bits == 0) return true; return nsub->float_type.bits <= nsuper->float_type.bits; } - // 其他类型 只有结构等价 相等 才视为子类型 已在前面处理 + // 其他情况:结构等价(已在相等判断中处理) return false; } +bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub, + spl_lang_type_id_t super) { + if (sub == 0 || super == 0) + return false; + if (sub == super) + return true; + + spl_lang_type_node_t *nsub = spl_lang_type_node(type, sub); + spl_lang_type_node_t *nsuper = spl_lang_type_node(type, super); + if (!nsub || !nsuper) + return false; + + // 语言级特殊类型 + if (nsub->kind == SPL_LANG_TYPE_NEVER) + return true; + if (nsuper->kind == SPL_LANG_TYPE_ANY) + return true; + if (nsub->kind == SPL_LANG_TYPE_INFER || nsuper->kind == SPL_LANG_TYPE_INFER) { + // 推断类型暂不处理子类型关系 + return false; + } + + // 对于简单类型,委托给底层类型判断 + // 如果语言级 kind 相同且底层类型可子类型,则成立 + if (nsub->kind == nsuper->kind) { + return spl_type_is_subtype(type, nsub->ir_type_id, nsuper->ir_type_id); + } + + // 特殊情况:slice 可以看作 array 的超集?暂不处理 + return false; +} + +spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, + spl_dbg_node_t dbg, usize ast_node_ref) { + spl_def_node_t n = {0}; + n.kind = kind; + n.name = name; + n.dbg_node = dbg; + n.lang_id = 0; + n.ast_node_ref = ast_node_ref; + vec_push(type->def_table, n); + return vec_size(type->def_table) - 1; +} + +void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id) { + spl_def_node_t *d = spl_def_node(type, id); + if (d) + d->lang_id = lang_id; +} + +spl_type_id_t spl_lang_type_get_ir_type(spl_type_t *type, spl_lang_type_id_t lang_id) { + spl_lang_type_node_t *n = spl_lang_type_node(type, lang_id); + return n ? n->ir_type_id : 0; +} + +spl_lang_type_id_t spl_def_get_lang_id(spl_type_t *type, spl_def_id_t def_id) { + spl_def_node_t *d = spl_def_node(type, def_id); + return d ? d->lang_id : 0; +} + +spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id) { + spl_lang_type_id_t lang = spl_def_get_lang_id(type, def_id); + return lang ? spl_lang_type_get_ir_type(type, lang) : 0; +} + +spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx) { + spl_type_node_t *n = spl_type_node(type, fn_tid); + if (!n || n->kind != SPL_TYPE_FN || idx >= vec_size(n->fn_type.params)) + return 0; + return vec_at(n->fn_type.params, idx); +} + static const spl_type_member_t *spl_type_agg_member_find(spl_type_t *type, spl_type_id_t tid, const char *name, usize *out_idx) { spl_type_node_t *n = spl_type_node(type, tid); - if (!n || !name) { + if (!n || !name) return NULL; - } if (n->kind == SPL_TYPE_STRUCT || n->kind == SPL_TYPE_UNION || n->kind == SPL_TYPE_ENUM || n->kind == SPL_TYPE_SHAPE) { - vec_for(n->agg_type.variants, i) { - const char *mn = vec_at(n->agg_type.variants, i).name; - if (strcmp(mn ? mn : "", name) == 0) { - if (out_idx) { + for (usize i = 0; i < vec_size(n->agg_type.variants); i++) { + spl_type_member_t *m = &n->agg_type.variants.data[i]; + if (m->name && strcmp(m->name, name) == 0) { + if (out_idx) *out_idx = i; - } - return &n->agg_type.variants.data[i]; + return m; } } } @@ -223,14 +435,14 @@ bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *na spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kind) { spl_type_node_t tn = {0}; tn.kind = kind; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; return spl_type_node_push(type, &tn); } spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_INT; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; tn.int_type.bits = bits; tn.int_type.is_signed = is_signed; return spl_type_node_push(type, &tn); @@ -239,7 +451,7 @@ spl_type_id_t spl_type_builder_int(spl_type_t *type, usize bits, int is_signed) spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_FLOAT; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; tn.float_type.bits = bits; return spl_type_node_push(type, &tn); } @@ -247,7 +459,7 @@ spl_type_id_t spl_type_builder_float(spl_type_t *type, usize bits) { spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_PTR; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; tn.ptr_type.pointee = pointee; return spl_type_node_push(type, &tn); } @@ -255,7 +467,7 @@ spl_type_id_t spl_type_builder_ptr(spl_type_t *type, spl_type_id_t pointee) { spl_type_id_t spl_type_builder_array(spl_type_t *type, spl_type_id_t element, usize len) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_ARRAY; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; tn.array_type.element = element; tn.array_type.len = len; return spl_type_node_push(type, &tn); @@ -265,7 +477,7 @@ spl_type_id_t spl_type_builder_fn(spl_type_t *type, spl_type_id_t ret, const spl usize nparams) { spl_type_node_t tn = {0}; tn.kind = SPL_TYPE_FN; - tn.lang_kind = SPL_LANG_TYPE_NONE; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; vec_init(tn.fn_type.params); for (usize i = 0; i < nparams; i++) { vec_push(tn.fn_type.params, params[i]); @@ -279,255 +491,282 @@ spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, spl_type_layout_t layout) { spl_type_node_t tn = {0}; tn.kind = tk; - tn.lang_kind = SPL_LANG_TYPE_NONE; tn.layout = layout; - tn.agg_type.variants = *variants; + tn.agg_type.variants = *variants; // 移动所有权 + vec_init(*variants); // 清空源 if (tk == SPL_TYPE_ENUM) { tn.agg_type.tag_type = tag_type; } else { tn.agg_type.tag_type = 0; } - vec_init(*variants); return spl_type_node_push(type, &tn); } -spl_type_id_t spl_type_make_unit(spl_type_t *type) { - spl_type_id_t id = spl_type_builder_simple(type, SPL_TYPE_UNIT); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +static spl_lang_type_id_t spl_lang_node_simple(spl_type_t *type, spl_lang_type_kind_t lang_kind, + spl_type_id_t ir_type_id) { + spl_lang_type_node_t node = {0}; + node.kind = lang_kind; + node.ir_type_id = ir_type_id; + return spl_lang_node_push(type, &node); } -spl_type_id_t spl_type_make_bool(spl_type_t *type) { - spl_type_id_t id = spl_type_builder_simple(type, SPL_TYPE_BOOL); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_error(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_ERROR); + return spl_lang_node_simple(type, SPL_LANG_TYPE_ERROR, ir); } -spl_type_id_t spl_type_make_any(spl_type_t *type) { - spl_type_id_t id = spl_type_builder_simple(type, SPL_TYPE_ANY); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_infer(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_INFER); + return spl_lang_node_simple(type, SPL_LANG_TYPE_INFER, ir); } -spl_type_id_t spl_type_make_never(spl_type_t *type) { - spl_type_id_t id = spl_type_builder_simple(type, SPL_TYPE_NEVER); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_never(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_NEVER); + return spl_lang_node_simple(type, SPL_LANG_TYPE_NEVER, ir); } -spl_type_id_t spl_type_make_int(spl_type_t *type, usize bits, int is_signed) { - spl_type_id_t id = spl_type_builder_int(type, bits, is_signed); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_any(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_ANY); + return spl_lang_node_simple(type, SPL_LANG_TYPE_ANY, ir); } -spl_type_id_t spl_type_make_float(spl_type_t *type, usize bits) { - spl_type_id_t id = spl_type_builder_float(type, bits); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_unit(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_UNIT); + return spl_lang_node_simple(type, SPL_LANG_TYPE_UNIT, ir); } -spl_type_id_t spl_type_make_ptr(spl_type_t *type, spl_type_id_t pointee) { - spl_type_id_t id = spl_type_builder_ptr(type, pointee); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_bool(spl_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_BOOL); + return spl_lang_node_simple(type, SPL_LANG_TYPE_BOOL, ir); } -spl_type_id_t spl_type_make_array(spl_type_t *type, spl_type_id_t elem, usize len) { - spl_type_id_t id = spl_type_builder_array(type, elem, len); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_int(spl_type_t *type, usize bits, int is_signed) { + spl_type_id_t ir = spl_type_builder_int(type, bits, is_signed); + return spl_lang_node_simple(type, SPL_LANG_TYPE_INT, ir); } -spl_type_id_t spl_type_make_fn(spl_type_t *type, spl_type_id_t ret, const spl_type_id_t *params, - usize nparams) { - spl_type_id_t id = spl_type_builder_fn(type, ret, params, nparams); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_float(spl_type_t *type, usize bits) { + spl_type_id_t ir = spl_type_builder_float(type, bits); + return spl_lang_node_simple(type, SPL_LANG_TYPE_FLOAT, ir); } -spl_type_id_t spl_type_make_agg(spl_type_t *type, spl_type_node_kind_t tk, - spl_type_member_vec_t *variants, spl_type_id_t tag_type, - spl_type_layout_t layout) { - spl_type_id_t id = spl_type_builder_agg(type, tk, variants, tag_type, layout); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_NONE; - return id; +spl_lang_type_id_t spl_lang_make_array(spl_type_t *type, spl_lang_type_id_t elem_lang, usize len) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + spl_type_id_t ir = spl_type_builder_array(type, elem_ir, len); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_ARRAY; + node.ir_type_id = ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); } -spl_type_id_t spl_type_make_slice(spl_type_t *type, spl_type_id_t elem) { - // 底层构造 struct {ptr, len} +spl_lang_type_id_t spl_lang_make_ptr(spl_type_t *type, spl_lang_type_id_t pointee_lang) { + spl_type_id_t pointee_ir = spl_lang_type_get_ir_type(type, pointee_lang); + if (!pointee_ir) + return 0; + spl_type_id_t ir = spl_type_builder_ptr(type, pointee_ir); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_PTR; + node.ir_type_id = ir; + node.extra.elem = pointee_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_slice(spl_type_t *type, spl_lang_type_id_t elem_lang) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + // 获取 usize 底层类型 + spl_type_id_t usize_ir = spl_type_builder_int(type, sizeof(void *) * 8, 0); + spl_type_id_t ptr_ir = spl_type_builder_ptr(type, elem_ir); + // 构建 struct { ptr, len } spl_type_member_vec_t members; vec_init(members); - - spl_type_id_t ptr_tid = spl_type_make_ptr(type, elem); - spl_type_member_t member_ptr = {.name = "ptr", .type_id = ptr_tid}; - vec_push(members, member_ptr); - - spl_type_id_t usize_tid = spl_type_make_int(type, sizeof(void *) * 8, false); - spl_type_member_t member_len = {.name = "len", .type_id = usize_tid}; - vec_push(members, member_len); - - spl_type_id_t id = - spl_type_make_agg(type, SPL_TYPE_STRUCT, &members, 0, (spl_type_layout_t){0}); - vec_free(members); // make_agg 已拷贝成员,原向量可释放 - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_SLICE; - return id; + spl_type_member_t m1 = {.name = "ptr", .type_id = ptr_ir}; + spl_type_member_t m2 = {.name = "len", .type_id = usize_ir}; + vec_push(members, m1); + vec_push(members, m2); + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); + // 语言级节点 + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_SLICE; + node.ir_type_id = struct_ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); } -spl_type_id_t spl_type_make_tuple(spl_type_t *type, spl_type_member_vec_t *variants) { - spl_type_id_t id = - spl_type_make_agg(type, SPL_TYPE_STRUCT, variants, 0, (spl_type_layout_t){0}); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_TUPLE; - return id; -} - -spl_type_id_t spl_type_make_range(spl_type_t *type, spl_type_id_t elem) { +spl_lang_type_id_t spl_lang_make_tuple(spl_type_t *type, const spl_lang_type_id_t *elems, + usize count) { spl_type_member_vec_t members; vec_init(members); - - spl_type_member_t member_start = {.name = "start", .type_id = elem}; - vec_push(members, member_start); - - spl_type_member_t member_end = {.name = "end", .type_id = elem}; - vec_push(members, member_end); - - spl_type_id_t id = - spl_type_make_agg(type, SPL_TYPE_STRUCT, &members, 0, (spl_type_layout_t){0}); - vec_free(members); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_RANGE; + for (usize i = 0; i < count; i++) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elems[i]); + if (!elem_ir) { + vec_free(members); + return 0; + } + char name[32]; + snprintf(name, sizeof(name), "%zu", i); + spl_type_member_t m = {.name = strdup(name), .type_id = elem_ir}; + vec_push(members, m); + } + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); + // 语言级节点 + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_TUPLE; + node.ir_type_id = struct_ir; + vec_init(node.extra.elems); + for (usize i = 0; i < count; i++) { + vec_push(node.extra.elems, elems[i]); + } + spl_lang_type_id_t id = spl_lang_node_push(type, &node); + if (!id) { + // 如果失败,释放临时成员名?但 strdup 的内存已进入底层类型表,不能释放 + // 这里底层类型表拥有这些字符串,所以没问题 + } return id; } -spl_type_id_t spl_type_make_infer(spl_type_t *type) { - // 使用底层 ERROR 类型作为占位,实际由 lang_kind 标识 - spl_type_id_t id = spl_type_builder_simple(type, SPL_TYPE_ERROR); - if (id) - spl_type_node(type, id)->lang_kind = SPL_LANG_TYPE_INFER; +spl_lang_type_id_t spl_lang_make_range(spl_type_t *type, spl_lang_type_id_t elem_lang) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + // 构建 struct { start, end } + spl_type_member_vec_t members; + vec_init(members); + spl_type_member_t m1 = {.name = "start", .type_id = elem_ir}; + spl_type_member_t m2 = {.name = "end", .type_id = elem_ir}; + vec_push(members, m1); + vec_push(members, m2); + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_RANGE; + node.ir_type_id = struct_ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_fn(spl_type_t *type, spl_lang_type_id_t ret_lang, + const spl_lang_type_id_t *params_lang, usize nparams) { + spl_type_id_t ret_ir = spl_lang_type_get_ir_type(type, ret_lang); + if (!ret_ir) + return 0; + spl_type_id_vec_t param_irs; + vec_init(param_irs); + for (usize i = 0; i < nparams; i++) { + spl_type_id_t pir = spl_lang_type_get_ir_type(type, params_lang[i]); + if (!pir) { + vec_free(param_irs); + return 0; + } + vec_push(param_irs, pir); + } + spl_type_id_t fn_ir = spl_type_builder_fn(type, ret_ir, param_irs.data, vec_size(param_irs)); + vec_free(param_irs); + // 语言级节点 + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_FN; + node.ir_type_id = fn_ir; + node.extra.fn.ret = ret_lang; + vec_init(node.extra.fn.params); + for (usize i = 0; i < nparams; i++) { + vec_push(node.extra.fn.params, params_lang[i]); + } + spl_lang_type_id_t id = spl_lang_node_push(type, &node); return id; } -spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { +spl_lang_type_id_t spl_lang_make_aggregate(spl_type_t *type, spl_lang_type_kind_t kind, + const char *name, const spl_lang_type_id_t *members_lang, + usize nmembers) { + // 确定底层 kind + spl_type_node_kind_t tk; + switch (kind) { + case SPL_LANG_TYPE_STRUCT: + tk = SPL_TYPE_STRUCT; + break; + case SPL_LANG_TYPE_UNION: + tk = SPL_TYPE_UNION; + break; + case SPL_LANG_TYPE_ENUM: + tk = SPL_TYPE_ENUM; + break; + case SPL_LANG_TYPE_SHAPE: + tk = SPL_TYPE_SHAPE; + break; + default: + return 0; + } + // 构建成员向量(成员名自动生成 "0","1"...) + spl_type_member_vec_t members; + vec_init(members); + for (usize i = 0; i < nmembers; i++) { + spl_type_id_t member_ir = spl_lang_type_get_ir_type(type, members_lang[i]); + if (!member_ir) { + vec_free(members); + return 0; + } + char field_name[32]; + snprintf(field_name, sizeof(field_name), "%zu", i); + spl_type_member_t m = {.name = strdup(field_name), .type_id = member_ir}; + vec_push(members, m); + } + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t agg_ir = spl_type_builder_agg(type, tk, &members, 0, layout); + // 语言级节点(没有额外信息,除了 kind 和 ir_type_id) + spl_lang_type_node_t node = {0}; + node.kind = kind; + node.ir_type_id = agg_ir; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_varargs(spl_type_t *type) { + // 底层类型使用 unit(无实际存储),语言级节点单独标记 + spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_UNIT); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_VARARGS; + node.ir_type_id = ir; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { if (!name || !*name) return 0; - - // 固定名称类型 + // 简单映射 if (strcmp(name, "bool") == 0) - return spl_type_builder_simple(type, SPL_TYPE_BOOL); + return spl_lang_make_bool(type); if (strcmp(name, "void") == 0) - return spl_type_builder_simple(type, SPL_TYPE_UNIT); + return spl_lang_make_unit(type); if (strcmp(name, "isize") == 0) - return spl_type_builder_int(type, sizeof(void *) * 8, true); + return spl_lang_make_int(type, sizeof(void *) * 8, 1); if (strcmp(name, "usize") == 0) - return spl_type_builder_int(type, sizeof(void *) * 8, false); - - // 动态模式:iN / uN / fN,N 为正整数 + return spl_lang_make_int(type, sizeof(void *) * 8, 0); + if (strcmp(name, "any") == 0) + return spl_lang_make_any(type); + // iN / uN / fN 模式 char prefix = name[0]; if (prefix == 'i' || prefix == 'u' || prefix == 'f') { const char *rest = name + 1; - if (*rest == '\0') - return 0; char *end; long bits = strtol(rest, &end, 10); if (end != rest && *end == '\0' && bits > 0) { if (prefix == 'i') - return spl_type_builder_int(type, (int)bits, true); + return spl_lang_make_int(type, (usize)bits, 1); if (prefix == 'u') - return spl_type_builder_int(type, (int)bits, false); + return spl_lang_make_int(type, (usize)bits, 0); if (prefix == 'f') - return spl_type_builder_float(type, (int)bits); + return spl_lang_make_float(type, (usize)bits); } } return 0; } -spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id) { - spl_def_node_t *def_node = spl_def_node(type, def_id); - Assert(def_node != NULL); - return def_node->type_id; -} - -spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, - spl_dbg_node_t dbg, usize ast_node_ref) { - spl_def_node_t n = {0}; - n.kind = kind; - n.name = name; - n.dbg_node = dbg; - n.ast_node_ref = ast_node_ref; - vec_push(type->def_table, n); - return vec_size(type->def_table) - 1; -} - -void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_type_id_t tid) { - spl_def_node_t *d = spl_def_node(type, id); - if (!d) { - return; - } - d->type_id = tid; -} - -spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx) { - spl_type_node_t *n = spl_type_node(type, fn_tid); - if (!n || n->kind != SPL_TYPE_FN || idx >= vec_size(n->fn_type.params)) - return 0; - return vec_at(n->fn_type.params, idx); -} - -void spl_type_init(spl_type_t *type) { - vec_init(type->type_table); - vec_push(type->type_table, (spl_type_node_t){0}); - map_init(type->type_map, spl_type_map_hash, spl_type_map_cmp); - vec_init(type->def_table); - vec_push(type->def_table, (spl_def_node_t){0}); -} - -void spl_type_drop(spl_type_t *type) { - vec_for(type->type_table, i) { - spl_type_node_t *n = &vec_at(type->type_table, i); - switch (n->kind) { - case SPL_TYPE_STRUCT: - case SPL_TYPE_UNION: - case SPL_TYPE_ENUM: - case SPL_TYPE_SHAPE: - vec_free(n->agg_type.variants); - break; - case SPL_TYPE_FN: - vec_free(n->fn_type.params); - break; - default: - break; - } - } - - map_free(type->type_map); - vec_free(type->type_table); - vec_free(type->def_table); -} - -spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id) { - if (!id || id >= vec_size(type->type_table)) - return NULL; - return &vec_at(type->type_table, id); -} - -spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id) { - if (!id || id >= vec_size(type->def_table)) - return NULL; - return &vec_at(type->def_table, id); -} - +/* ========== 转储函数 ========== */ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { spl_type_node_t *n = spl_type_node(type, id); if (!n) { @@ -552,24 +791,22 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { break; case SPL_TYPE_FORALL: case SPL_TYPE_EXISTS: - TODO(); + printf("quant"); break; case SPL_TYPE_BOOL: printf("bool"); break; case SPL_TYPE_INT: - if (n->int_type.bits == 0) { + if (n->int_type.bits == 0) printf("comptime_int"); - } else { + else printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); - } break; case SPL_TYPE_FLOAT: - if (n->float_type.bits == 0) { + if (n->float_type.bits == 0) printf("comptime_float"); - } else { + else printf("f%zu", n->float_type.bits); - } break; case SPL_TYPE_PTR: printf("*"); @@ -582,46 +819,125 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { case SPL_TYPE_STRUCT: case SPL_TYPE_UNION: case SPL_TYPE_ENUM: - case SPL_TYPE_SHAPE: - switch (n->kind) { - case SPL_TYPE_STRUCT: - printf("struct{\n"); - break; - case SPL_TYPE_UNION: - printf("union{\n"); - break; - case SPL_TYPE_ENUM: - printf("enum{\n"); - break; - case SPL_TYPE_SHAPE: - printf("shape{\n"); - break; - default: - UNREACHABLE(); - break; - } - vec_for(n->agg_type.variants, i) { - if (i) { + case SPL_TYPE_SHAPE: { + const char *kw = "struct"; + if (n->kind == SPL_TYPE_UNION) + kw = "union"; + else if (n->kind == SPL_TYPE_ENUM) + kw = "enum"; + else if (n->kind == SPL_TYPE_SHAPE) + kw = "shape"; + printf("%s{", kw); + for (usize i = 0; i < vec_size(n->agg_type.variants); i++) { + if (i) printf(", "); - } - spl_type_member_t *member = &vec_at(n->agg_type.variants, i); - printf("%s:", member->name ? member->name : "?"); - spl_type_pure_dump(type, member->type_id); + spl_type_member_t *m = &n->agg_type.variants.data[i]; + printf("%s:", m->name ? m->name : "?"); + spl_type_pure_dump(type, m->type_id); } printf("}"); break; - case SPL_TYPE_FN: { + } + case SPL_TYPE_FN: printf("fn("); - vec_for(n->fn_type.params, i) { - if (i) { + for (usize i = 0; i < vec_size(n->fn_type.params); i++) { + if (i) printf(","); - } spl_type_pure_dump(type, vec_at(n->fn_type.params, i)); } printf(")"); spl_type_pure_dump(type, n->fn_type.ret); break; } +} + +void spl_lang_type_dump(spl_type_t *type, spl_lang_type_id_t id) { + spl_lang_type_node_t *n = spl_lang_type_node(type, id); + if (!n) { + printf("none"); + return; + } + switch (n->kind) { + case SPL_LANG_TYPE_ERROR: + printf("error"); + break; + case SPL_LANG_TYPE_INFER: + printf("infer"); + break; + case SPL_LANG_TYPE_NEVER: + printf("never"); + break; + case SPL_LANG_TYPE_ANY: + printf("any"); + break; + case SPL_LANG_TYPE_UNIT: + printf("unit"); + break; + case SPL_LANG_TYPE_BOOL: + printf("bool"); + break; + case SPL_LANG_TYPE_VARARGS: + printf("..."); + break; + case SPL_LANG_TYPE_INT: { + spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); + if (tn && tn->int_type.bits == 0) + printf("comptime_int"); + else + spl_type_pure_dump(type, n->ir_type_id); + break; + } + case SPL_LANG_TYPE_FLOAT: { + spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); + if (tn && tn->float_type.bits == 0) + printf("comptime_float"); + else + spl_type_pure_dump(type, n->ir_type_id); + break; + } + case SPL_LANG_TYPE_PTR: + printf("*"); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_ARRAY: { + spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); + printf("[%zu]", tn->array_type.len); + spl_type_pure_dump(type, n->ir_type_id); + } break; + case SPL_LANG_TYPE_SLICE: + printf("[]"); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_TUPLE: + printf("("); + for (usize i = 0; i < vec_size(n->extra.elems); i++) { + if (i) + printf(","); + spl_lang_type_dump(type, vec_at(n->extra.elems, i)); + } + printf(")"); + break; + case SPL_LANG_TYPE_RANGE: + spl_lang_type_dump(type, n->extra.elem); + printf(".."); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_FN: + printf("fn("); + for (usize i = 0; i < vec_size(n->extra.fn.params); i++) { + if (i) + printf(","); + spl_lang_type_dump(type, vec_at(n->extra.fn.params, i)); + } + printf(")"); + spl_lang_type_dump(type, n->extra.fn.ret); + break; + case SPL_LANG_TYPE_STRUCT: + case SPL_LANG_TYPE_UNION: + case SPL_LANG_TYPE_ENUM: + case SPL_LANG_TYPE_SHAPE: + spl_type_pure_dump(type, n->ir_type_id); + break; } } @@ -631,8 +947,7 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { printf("none"); return; } - - const char *def_kind_name = "null"; + const char *def_kind_name = "unknown"; switch (node->kind) { case SPL_DEF_ERROR: def_kind_name = "error"; @@ -666,12 +981,12 @@ void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { } break; case SPL_DEF_DISTINCT: - def_kind_name = "newtype"; + def_kind_name = "distinct"; break; case SPL_DEF_ALIAS: - def_kind_name = "sametypes"; + def_kind_name = "alias"; break; } - printf("kind=%s type_id=%zu name=%s", def_kind_name, node->type_id, + printf("kind=%s lang_id=%zu name=%s", def_kind_name, node->lang_id, node->name ? node->name : "?"); } diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 2a2d239..3bff951 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -6,6 +6,8 @@ typedef usize spl_type_id_t; /* 0 is error */ typedef VEC(spl_type_id_t) spl_type_id_vec_t; +typedef usize spl_lang_type_id_t; /* 0 is error */ +typedef VEC(spl_lang_type_id_t) spl_lang_type_id_vec_t; typedef usize spl_def_id_t; /* 0 is error */ typedef VEC(spl_def_id_t) spl_def_id_vec_t; @@ -13,8 +15,8 @@ typedef enum { SPL_TYPE_ERROR, SPL_TYPE_NEVER, // bottom type SPL_TYPE_ANY, // top type - SPL_TYPE_INFER, // auto type SPL_TYPE_UNIT, + SPL_TYPE_INFER, SPL_TYPE_BOOL, SPL_TYPE_INT, SPL_TYPE_FLOAT, @@ -29,14 +31,6 @@ typedef enum { SPL_TYPE_SHAPE, } spl_type_node_kind_t; -typedef enum { - SPL_LANG_TYPE_NONE, // 普通底层类型(如 int, ptr 等) - SPL_LANG_TYPE_INFER, // 类型推断占位符 - SPL_LANG_TYPE_SLICE, // 切片(底层 struct {ptr, len}) - SPL_LANG_TYPE_TUPLE, // 元组(底层 struct,字段名为数字) - SPL_LANG_TYPE_RANGE, // 范围(可选) -} spl_lang_type_node_kind_t; - typedef enum { SPL_TYPE_LAYOUT_AUTO, SPL_TYPE_LAYOUT_EXTERN_C, @@ -57,7 +51,6 @@ typedef VEC(spl_type_member_t) spl_type_member_vec_t; typedef struct { spl_type_node_kind_t kind; - spl_lang_type_node_kind_t lang_kind; spl_type_layout_t layout; // attribute union { struct { @@ -89,6 +82,43 @@ typedef struct { } spl_type_node_t; typedef VEC(spl_type_node_t) spl_type_node_vec_t; +typedef enum { + SPL_LANG_TYPE_ERROR, + SPL_LANG_TYPE_INFER, + SPL_LANG_TYPE_NEVER, + SPL_LANG_TYPE_ANY, + SPL_LANG_TYPE_UNIT, + SPL_LANG_TYPE_BOOL, + SPL_LANG_TYPE_INT, + SPL_LANG_TYPE_FLOAT, + SPL_LANG_TYPE_PTR, + SPL_LANG_TYPE_ARRAY, + SPL_LANG_TYPE_SLICE, + SPL_LANG_TYPE_TUPLE, + SPL_LANG_TYPE_RANGE, + SPL_LANG_TYPE_FN, + SPL_LANG_TYPE_STRUCT, + SPL_LANG_TYPE_UNION, + SPL_LANG_TYPE_ENUM, + SPL_LANG_TYPE_SHAPE, + SPL_LANG_TYPE_VARARGS, +} spl_lang_type_kind_t; + +typedef struct { + spl_lang_type_kind_t kind; + spl_type_id_t ir_type_id; + union { + spl_lang_type_id_t elem; + spl_lang_type_id_vec_t elems; + struct { + spl_lang_type_id_vec_t params; + spl_lang_type_id_t ret; + } fn; + } extra; +} spl_lang_type_node_t; +typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t; +typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t; + typedef enum { SPL_DEF_ERROR, SPL_DEF_SCALAR, @@ -110,7 +140,7 @@ typedef struct { } builtin_kind; const char *name; spl_dbg_node_t dbg_node; - spl_type_id_t type_id; + spl_lang_type_id_t lang_id; usize ast_node_ref; } spl_def_node_t; typedef VEC(spl_def_node_t) spl_def_node_vec_t; @@ -119,6 +149,8 @@ typedef MAP(usize, spl_type_id_t) spl_type_node_map_t; typedef struct { spl_type_node_vec_t type_table; spl_type_node_map_t type_map; + spl_lang_type_vec_t lang_table; + spl_lang_type_map_t lang_map; spl_def_node_vec_t def_table; } spl_type_t; @@ -127,16 +159,23 @@ void spl_type_drop(spl_type_t *type); void spl_type_def_dump(spl_type_t *type, spl_def_id_t id); void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); +void spl_lang_type_dump(spl_type_t *type, spl_lang_type_id_t id); spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id); +spl_lang_type_node_t *spl_lang_type_node(const spl_type_t *type, spl_lang_type_id_t id); spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id); -/* 判断 sub 是否是 super 的子类型 值域包含关系 */ +bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub, + spl_lang_type_id_t super); bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super); -spl_type_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, - spl_dbg_node_t dbg, usize ast_node_ref); -void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_type_id_t tid); +spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, + spl_dbg_node_t dbg, usize ast_node_ref); +void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id); + +spl_type_id_t spl_lang_type_get_ir_type(spl_type_t *type, spl_lang_type_id_t lang_id); +spl_lang_type_id_t spl_def_get_lang_id(spl_type_t *type, spl_def_id_t def_id); +spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id); spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx); const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, const char *name); @@ -154,29 +193,27 @@ spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, spl_type_member_vec_t *variants, spl_type_id_t tag_type, spl_type_layout_t layout); -spl_type_id_t spl_type_make_unit(spl_type_t *type); -spl_type_id_t spl_type_make_never(spl_type_t *type); -spl_type_id_t spl_type_make_any(spl_type_t *type); -spl_type_id_t spl_type_make_bool(spl_type_t *type); -spl_type_id_t spl_type_make_int(spl_type_t *type, usize bits, int is_signed); -spl_type_id_t spl_type_make_float(spl_type_t *type, usize bits); -spl_type_id_t spl_type_make_ptr(spl_type_t *type, spl_type_id_t pointee); -spl_type_id_t spl_type_make_array(spl_type_t *type, spl_type_id_t elem, usize len); -spl_type_id_t spl_type_make_slice(spl_type_t *type, spl_type_id_t elem); -spl_type_id_t spl_type_make_tuple(spl_type_t *type, spl_type_member_vec_t *variants); -spl_type_id_t spl_type_make_range(spl_type_t *type, spl_type_id_t elem); -spl_type_id_t spl_type_make_fn(spl_type_t *type, spl_type_id_t ret, const spl_type_id_t *params, - usize nparams); -spl_type_id_t spl_type_make_agg(spl_type_t *type, spl_type_node_kind_t tk, - spl_type_member_vec_t *variants, spl_type_id_t tag_type, - spl_type_layout_t layout); -spl_type_id_t spl_type_make_infer(spl_type_t *type); -spl_type_id_t spl_type_make_slice(spl_type_t *type, spl_type_id_t elem_tid); -spl_type_id_t spl_type_make_tuple(spl_type_t *type, spl_type_member_vec_t *variants); -spl_type_id_t spl_type_make_range(spl_type_t *type, spl_type_id_t elem_tid); +spl_lang_type_id_t spl_lang_make_error(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_infer(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_never(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_any(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_unit(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_bool(spl_type_t *type); +spl_lang_type_id_t spl_lang_make_int(spl_type_t *type, usize bits, int is_signed); +spl_lang_type_id_t spl_lang_make_float(spl_type_t *type, usize bits); +spl_lang_type_id_t spl_lang_make_ptr(spl_type_t *type, spl_lang_type_id_t pointee); +spl_lang_type_id_t spl_lang_make_array(spl_type_t *type, spl_lang_type_id_t elem, usize len); +spl_lang_type_id_t spl_lang_make_slice(spl_type_t *type, spl_lang_type_id_t elem); +spl_lang_type_id_t spl_lang_make_tuple(spl_type_t *type, const spl_lang_type_id_t *elems, + usize count); +spl_lang_type_id_t spl_lang_make_range(spl_type_t *type, spl_lang_type_id_t elem); +spl_lang_type_id_t spl_lang_make_fn(spl_type_t *type, spl_lang_type_id_t ret, + const spl_lang_type_id_t *params, usize nparams); +spl_lang_type_id_t spl_lang_make_aggregate(spl_type_t *type, spl_lang_type_kind_t kind, + const char *name, const spl_lang_type_id_t *members, + usize nmembers); +spl_lang_type_id_t spl_lang_make_varargs(spl_type_t *type); -spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name); - -spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id); +spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name); #endif /* __SPL_TYPE_H__ */