diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index e9af6e3..f1db83a 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -1310,7 +1310,8 @@ static spl_ast_node_ref_t parse_postfix(parser_t *p) { } } else if (t->type == TOK_L_BRACKET) { advance(p); - spl_ast_node_ref_t begin = parse_expr(p); + int range_prec = binary_op_info[SPL_OP_RANGE].prec; + spl_ast_node_ref_t begin = parse_expr_prec(p, range_prec + 1); if (peek(p) && peek(p)->type == TOK_RANGE) { advance(p); spl_ast_node_ref_t end = 0; @@ -1432,15 +1433,17 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) { } else if (nx->type == TOK_L_BRACKET) { // 匿名数组字面量:. [ elems ] advance(p); // 消费 '[' - spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ANON_ARRAY_LIT, t); - spl_ast_node_t *arr = node_at(p->ast, ref); - arr->anon_array_literal.elems = parse_expr_list(p); + // 先解析元素列表,避免节点扩容导致 arr 指针失效 + spl_ast_node_ref_vec_t elems = parse_expr_list(p); const spl_tok_t *close = peek(p); if (!close || close->type != TOK_R_BRACKET) { SPL_FATAL(close, "expected ']'"); - return ref; + return 0; } - advance(p); + advance(p); // 消费 ']' + spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_ANON_ARRAY_LIT, t); + spl_ast_node_t *arr = node_at(p->ast, ref); + arr->anon_array_literal.elems = elems; return ref; } else { SPL_FATAL(nx, "expected '{' or '[' after '.'"); diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 434661b..95ac674 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -8,13 +8,16 @@ void spl_scope_init(spl_scope_t *scope) { } void spl_scope_drop(spl_scope_t *scope) { + for (usize i = 0; i < vec_size(scope->scopes); ++i) { + map_free(vec_at(scope->scopes, i).symbols); + } vec_free(scope->scopes); scope->current_scope = 0; scope->root_scope = 0; } spl_scope_id_t spl_scope_alloc(spl_scope_t *scope) { - spl_scope_node_t n; + spl_scope_node_t n = {0}; n.parent = scope->current_scope; map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR); vec_push(scope->scopes, n); @@ -26,11 +29,10 @@ bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol LOG_FATAL("sema scope insert error"); return false; } - spl_symbol_t old = {0}; spl_scope_node_t *node = &vec_at(scope->scopes, id); + spl_symbol_t old = {0}; if (map_get(node->symbols, symbol.name, &old)) { - // spl_def_node(sema->type, old); TODO debug node - SPL_ERROR(&(spl_dbg_node_t){0}, "find same symbol %s", symbol.name); + SPL_ERROR(&(spl_dbg_node_t){0}, "duplicate symbol `%s`", symbol.name); return false; } map_put(node->symbols, symbol.name, symbol); @@ -38,9 +40,8 @@ bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol } bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { - if (scope == NULL || name == NULL || out == NULL) { + if (!scope || !name || !out) return false; - } for (spl_scope_id_t id = scope->current_scope; id != 0; id = vec_at(scope->scopes, id).parent) { spl_scope_node_t *s = &vec_at(scope->scopes, id); if (map_get(s->symbols, name, out)) { @@ -51,1024 +52,1092 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { return false; } -// Parse once -static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { - Assert(sema != NULL && ref != 0); - spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - spl_symbol_t symbol = {0}; - Assert(n != NULL); - switch (n->kind) { - case SPL_AST_CONTAINER_MEMBERS: { - symbol.name = "$file"; - symbol.kind = SPL_SYMBOL_KIND_TYPE; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, ref); - n->resolved_def_id = symbol.node; - - spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); - sema->scope->current_scope = scope_id; - sema->scope->root_scope = scope_id; - spl_scope_insert(sema->scope, scope_id, symbol); - vec_for(n->container_members, i) { sema_collect(sema, vec_at(n->container_members, i)); } - break; - } - case SPL_AST_TYPE_DECL: { - symbol.name = n->type_decl.name; - symbol.kind = SPL_SYMBOL_KIND_TYPE; - spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); - if (!te) { - SPL_ERROR(&n->dbg, "type_decl must have type_expr"); - sema->error_count++; - return; - } - - switch (te->kind) { - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_ENUM: - case SPL_AST_TYPE_SHAPE: /* TODO for shape */ - symbol.node = spl_def_alloc(sema->type, SPL_DEF_AGG, symbol.name, te->dbg, ref); - n->resolved_def_id = symbol.node; - spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); - spl_scope_id_t old_id = sema->scope->current_scope; - spl_scope_insert(sema->scope, old_id, symbol); - sema->scope->current_scope = scope_id; - vec_for(te->type_expr.aggregate_list, i) { - spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); - sema_collect(sema, mref); - } - sema->scope->current_scope = old_id; - break; - default: - symbol.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, symbol.name, te->dbg, ref); - n->resolved_def_id = symbol.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - break; - } - } break; - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: { - symbol.name = n->fn_decl.name; - symbol.kind = SPL_SYMBOL_KIND_FN; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_FN, symbol.name, n->dbg, ref); - n->resolved_def_id = symbol.node; - // TODO same type avaliable insert twice for decl and define but define must only once - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - } break; - case SPL_AST_VAR_DECL: - case SPL_AST_CONST_DECL: { - symbol.name = n->var_const_decl.name; - symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); - n->resolved_def_id = symbol.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - } break; - default: - break; - } -} - -// Parse twice - -// use for assign_expr as_expr -static spl_type_id_t sema_coerce(spl_sema_t *sema, spl_type_id_t to, spl_type_id_t from) { - // var := from - if (to == 0) { - return from; - } - // error - if (from == 0) { - return 0; - } - // same - if (to == from) { - return to; - } - spl_type_node_t *tn = spl_type_node(sema->type, to); - spl_type_node_t *fn = spl_type_node(sema->type, from); - Assert(tn != NULL && fn != NULL); - switch (fn->kind) { - case SPL_TYPE_UNDEFINED: - return to; - case SPL_TYPE_NULL: - if (tn->kind == SPL_TYPE_PTR || tn->kind == SPL_TYPE_SLICE) { - return to; - } - break; - case SPL_TYPE_INT: - if (tn->kind != SPL_TYPE_INT) { - break; - } - - // var = comptime_int - if (tn->int_type.bits > 0 && fn->int_type.bits == 0) { - return to; - } - - // not same signed - if (tn->int_type.is_signed != fn->int_type.is_signed) { - break; - } - - // var i32 = i32/i16 - if (tn->int_type.bits >= fn->int_type.bits) { - return to; - } - break; - case SPL_TYPE_FLOAT: - // TODO - break; - case SPL_TYPE_ARRAY: - // TODO - break; - default: - break; - } - return 0; -} - -// use for op_expr -static spl_type_id_t sema_coerce_balance(spl_sema_t *sema, spl_type_id_t t1, spl_type_id_t t2) { - // error - if (t1 == 0 || t2 == 0) { - return 0; - } - // same - 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); - Assert(n1 != NULL && n2 != NULL); - - // TODO 应该推导类型 - if (n1->kind == SPL_TYPE_UNDEFINED && n1->kind == SPL_TYPE_UNDEFINED) { - return 0; - } - - if (n1->kind == SPL_TYPE_UNDEFINED) { - return t2; - } - if (n2->kind == SPL_TYPE_UNDEFINED) { - return t1; - } - if (n1->kind == SPL_TYPE_NULL) { - return (n2->kind == SPL_TYPE_PTR || n2->kind == SPL_TYPE_SLICE) ? t2 : 0; - } - if (n2->kind == SPL_TYPE_NULL) { - return (n1->kind == SPL_TYPE_PTR || n1->kind == SPL_TYPE_SLICE) ? t1 : 0; - } - - if (n1->kind != n2->kind) { - return 0; - } - - switch (n1->kind) { - case SPL_TYPE_INT: - if (n1->int_type.is_signed != n2->int_type.is_signed) { - return 0; - } - return n1->int_type.bits >= n2->int_type.bits ? t1 : t2; - case SPL_TYPE_FLOAT: - return n1->float_type.bits >= n2->float_type.bits ? t1 : t2; - default: - break; - } - 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_builder_simple(sema->type, SPL_TYPE_BOOL); - return sema_coerce(sema, bool_tid, from) == bool_tid; -} - -// FIXME using lib ops -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); - if (!n) - return 0; - switch (n->kind) { - case SPL_TYPE_SLICE: - return n->slice_element; - case SPL_TYPE_ARRAY: - return n->array_type.element; - case SPL_TYPE_PTR: - return n->ptr_pointee; - case SPL_TYPE_RANGE: - return n->range_element; - default: - return 0; - } -} - static inline void sema_push_scope(spl_sema_t *sema) { - spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); + spl_scope_id_t new_scope = spl_scope_alloc(sema->scope); sema->store_scope = sema->scope->current_scope; - sema->scope->current_scope = scope_id; + sema->scope->current_scope = new_scope; } static inline void sema_pop_scope(spl_sema_t *sema) { sema->scope->current_scope = sema->store_scope; } -static spl_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { - if (ref == 0) { +static spl_type_id_t sema_coerce(spl_sema_t *sema, spl_type_id_t to, spl_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; } - Assert(sema != NULL); + + spl_type_node_t *from_node = spl_type_node(sema->type, from); + if (!to_node || !from_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) { + return to; + } + } else if (from_node->kind == SPL_TYPE_FLOAT && from_node->float_type.bits == 0) { + if (to_node->kind == SPL_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) { + return to; + } + } + + // 常规子类型检查 + if (spl_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) { + 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); + 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) + return t2; + if (n2->kind == SPL_TYPE_NEVER) + return t1; + + // 其余逻辑保持原样,但最好改为使用子类型判断 + if (spl_type_is_subtype(sema->type, t1, t2)) + return t2; + if (spl_type_is_subtype(sema->type, t2, t1)) + return t1; + + 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); + 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); + 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; + } + 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; + } + } +} + +static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - Assert(n != NULL); + if (!n) + return; + switch (n->kind) { - case SPL_AST_NONE: - UNREACHABLE(); - break; case SPL_AST_CONTAINER_MEMBERS: { - vec_for(n->container_members, i) { sema_parse(sema, vec_at(n->container_members, i)); } - } break; - case SPL_AST_FN_DECL: { - if (n->resolved_def_id == 0) { - Panic("fn `%s` don't collect", n->fn_decl.name); + spl_symbol_t file_sym = {.name = "$file", .kind = SPL_SYMBOL_KIND_TYPE}; + file_sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, ref); + n->resolved_def_id = file_sym.node; + + spl_scope_id_t root_scope = spl_scope_alloc(sema->scope); + sema->scope->current_scope = root_scope; + sema->scope->root_scope = root_scope; + spl_scope_insert(sema->scope, root_scope, file_sym); + + for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { + sema_collect(sema, vec_at(n->container_members.declarations, i)); } - /* 前向/extern 声明:只解析签名并构建 fn 类型,不进入 scope */ - spl_type_id_vec_t params_type; - vec_init(params_type); - vec_for(n->fn_decl.param_list, i) { - spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); - spl_ast_node_t *pd = spl_ast_node(sema->ast, ref); - if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr) { - vec_push(params_type, sema_parse(sema, pd->param_decl.type_expr)); - } else { - // TODO variadic - } - } - spl_type_id_t ret_id = sema_parse(sema, n->fn_decl.type_expr); - spl_type_id_t fntid = spl_type_builder_fn( - sema->type, ret_id, vec_unsafe_get_data(params_type), vec_size(params_type)); - // Move params_type don't need free - spl_def_resolve(sema->type, n->resolved_def_id, fntid); break; } - case SPL_AST_FN_DEFINE: { - if (n->resolved_def_id == 0) { - Panic("fn `%s` don't collect", n->fn_decl.name); - } - sema_push_scope(sema); - - spl_type_id_vec_t params_type; - vec_init(params_type); - - vec_for(n->fn_decl.param_list, i) { - spl_ast_node_ref_t ref = vec_at(n->fn_decl.param_list, i); - spl_ast_node_t *node = spl_ast_node(sema->ast, ref); - if (!node || node->kind != SPL_AST_PARAM_DECL || !node->param_decl.type_expr) { - // TODO variadic - continue; - } - spl_type_id_t tid = sema_parse(sema, ref); - Assert(node->kind == SPL_AST_PARAM_DECL); - - vec_push(params_type, tid); - - if (node->resolved_def_id) { - spl_def_resolve(sema->type, node->resolved_def_id, tid); - } - } - spl_type_id_t ret_id = sema_parse(sema, n->fn_decl.type_expr); - - spl_type_id_t fntid = spl_type_builder_fn( - sema->type, ret_id, vec_unsafe_get_data(params_type), vec_size(params_type)); - // Move params_type don't need free - spl_def_resolve(sema->type, n->resolved_def_id, fntid); - - spl_type_id_t old_ret = sema->current_fn_ret_tid; - sema->current_fn_ret_tid = ret_id; - sema_parse(sema, n->fn_decl.block); - sema->current_fn_ret_tid = old_ret; - sema_pop_scope(sema); - } break; case SPL_AST_TYPE_DECL: { - if (!n->type_decl.type_expr) { - break; - } + spl_symbol_t sym = {.name = n->type_decl.name, .kind = SPL_SYMBOL_KIND_TYPE}; spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); if (!te) { - break; + SPL_ERROR(&n->dbg, "type declaration `%s` missing type expression", n->type_decl.name); + sema->error_count++; + return; } - switch (te->kind) { - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_ENUM: { - spl_type_member_vec_t members; - vec_init(members); - /* 第一遍:只收字段(MEMBER_DECL)的类型,构建容器类型并 resolve; - * 方法(fn)留到类型 resolve 后再处理,否则方法体引用自身类型会拿到未解析的 0 */ - vec_for(te->type_expr.aggregate_list, i) { - spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); - spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); - if (!mn || mn->kind != SPL_AST_MEMBER_DECL) - continue; - spl_type_id_t mtid = sema_parse(sema, mref); - spl_type_member_t m = {0}; - m.name = mn->member_decl.name; - m.type_id = mtid; - m.ast_node_ref = mref; - vec_push(members, m); - } - spl_type_node_kind_t tk = te->kind == SPL_AST_TYPE_UNION ? SPL_TYPE_UNION - : te->kind == SPL_AST_TYPE_ENUM ? SPL_TYPE_ENUM - : SPL_TYPE_STRUCT; - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; - // TODO tag type - spl_type_id_t tid = spl_type_builder_agg( - sema->type, tk, vec_unsafe_get_data(members), vec_size(members), - spl_type_builder_int(sema->type, 32, 1), layout); - // Move members don't need free + if (te->kind == SPL_AST_TYPE_AGGREGATE) { + sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, sym.name, te->dbg, ref); + n->resolved_def_id = sym.node; + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); - spl_def_resolve(sema->type, n->resolved_def_id, tid); - /* 第二遍:方法 body(struct 类型已 resolve,可引用自身类型) */ - vec_for(te->type_expr.aggregate_list, i) { - spl_ast_node_ref_t mref = vec_at(te->type_expr.aggregate_list, i); - spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); - if (mn && mn->kind == SPL_AST_FN_DEFINE) - sema_parse(sema, mref); + spl_scope_id_t old_scope = sema->scope->current_scope; + spl_scope_id_t inner_scope = spl_scope_alloc(sema->scope); + sema->scope->current_scope = inner_scope; + + for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { + sema_collect(sema, vec_at(te->type_aggregate.members, i)); } - break; + sema->scope->current_scope = old_scope; + } else { + sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref); + n->resolved_def_id = sym.node; + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); } - case SPL_AST_TYPE_SHAPE: /* TODO */ - vec_for(te->type_expr.aggregate_list, i) { - sema_parse(sema, vec_at(te->type_expr.aggregate_list, i)); - } - break; - default: { - spl_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); - spl_def_resolve(sema->type, n->resolved_def_id, tid); - break; - } - } - } break; + break; + } + case SPL_AST_FN_DECL: { + spl_symbol_t sym = {.name = n->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN}; + sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, ref); + n->resolved_def_id = sym.node; + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); + break; + } case SPL_AST_VAR_DECL: case SPL_AST_CONST_DECL: { + spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern); + if (pat && pat->kind == SPL_AST_PATTERN_IDENT) { + const char *name = pat->pattern_ident.name; + spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR}; + sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref); + n->resolved_def_id = sym.node; + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); + } else { + SPL_ERROR(&n->dbg, "unsupported variable pattern (only simple identifier)"); + sema->error_count++; + } + break; + } + case SPL_AST_TOP_LEVEL_BLOCK: + if (n->top_level_block.block) { + sema_collect(sema, n->top_level_block.block); + } + break; + default: + break; + } +} + +static spl_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); + if (!n) + return 0; + + switch (n->kind) { + case SPL_AST_CONTAINER_MEMBERS: + for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { + sema_parse(sema, vec_at(n->container_members.declarations, i)); + } + return 0; + + case SPL_AST_FN_DECL: { if (n->resolved_def_id == 0) { - spl_symbol_t symbol = {0}; - symbol.name = n->var_const_decl.name; - symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); - n->resolved_def_id = symbol.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + Panic("fn `%s` not collected", n->fn_decl.name); } - spl_type_id_t decl_tid = 0; - if (n->var_const_decl.type_expr) { - decl_tid = sema_parse(sema, n->var_const_decl.type_expr); + + spl_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); + } } - if (n->var_const_decl.expr == 0) { - SPL_ERROR(&n->dbg, "must be assign"); + spl_type_id_t ret_tid = sema_parse(sema, n->fn_decl.ret_type); + spl_type_id_t fn_tid = spl_type_make_fn( + sema->type, ret_tid, vec_unsafe_get_data(param_types), vec_size(param_types)); + vec_free(param_types); + spl_def_resolve(sema->type, n->resolved_def_id, fn_tid); + + if (n->fn_decl.body) { + sema_push_scope(sema); + 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) { + 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_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; + sema->current_fn_ret_tid = ret_tid; + sema_parse(sema, n->fn_decl.body); + sema->current_fn_ret_tid = old_ret; + sema_pop_scope(sema); + } + return fn_tid; + } + + case SPL_AST_TYPE_DECL: { + if (!n->type_decl.type_expr) + break; + spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); + if (!te) + break; + + if (te->kind == SPL_AST_TYPE_AGGREGATE) { + spl_type_member_vec_t members; + vec_init(members); + 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_type_member_t m = {.name = mn->member_decl.name, + .type_id = mtid, + .ast_node_ref = vec_at(te->type_aggregate.members, i)}; + vec_push(members, m); + } + } + + spl_type_node_kind_t tk; + if (strcmp(te->type_aggregate.kind_name, "struct") == 0) + tk = SPL_TYPE_STRUCT; + else if (strcmp(te->type_aggregate.kind_name, "union") == 0) + tk = SPL_TYPE_UNION; + else if (strcmp(te->type_aggregate.kind_name, "enum") == 0) + tk = SPL_TYPE_ENUM; + else + 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); + vec_free(members); + spl_def_resolve(sema->type, n->resolved_def_id, agg_tid); + + // 处理聚合内部的函数声明 + 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_FN_DECL) { + sema_parse(sema, vec_at(te->type_aggregate.members, i)); + } + } + } else { + // 标量类型别名,仍然使用 def_resolve 关联已有类型 + spl_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); + spl_def_resolve(sema->type, n->resolved_def_id, tid); + } + break; + } + + case SPL_AST_VAR_DECL: + case SPL_AST_CONST_DECL: { + spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern); + if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) { + SPL_ERROR(&n->dbg, "unsupported variable pattern"); + sema->error_count++; + return 0; + } + const char *name = pat->pattern_ident.name; + + if (n->resolved_def_id == 0) { + spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR}; + sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref); + n->resolved_def_id = sym.node; + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); + } + + spl_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); + } + if (n->var_const_decl.init_expr == 0) { + SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name); + sema->error_count++; return 0; } - spl_type_id_t et = sema_parse(sema, n->var_const_decl.expr); - decl_tid = sema_coerce(sema, decl_tid, et); + spl_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, "decl type must not none %d"); - sema->error_count += 1; + SPL_ERROR(&n->dbg, "cannot infer type for variable `%s`", name); + sema->error_count++; + return 0; } spl_def_resolve(sema->type, n->resolved_def_id, decl_tid); - } break; + return decl_tid; + } + case SPL_AST_MEMBER_DECL: { - /* 字段/变体不建 def, 类型由 TYPE_DECL 组装成员时统一构造 */ - spl_type_id_t mtid = 0; if (n->member_decl.type_expr) { - mtid = sema_parse(sema, n->member_decl.type_expr); + return sema_parse(sema, n->member_decl.type_expr); } - return mtid; - } break; - case SPL_AST__COMPTIME_STMT: - case SPL_AST__DIRECTIVE_BLOCK: - break; + return 0; + } + case SPL_AST_PARAM_DECL: { - if (n->resolved_def_id == 0) { - spl_symbol_t symbol = {0}; - symbol.name = n->param_decl.name; - symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_VAR, symbol.name, n->dbg, ref); - n->resolved_def_id = symbol.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - } - spl_type_id_t ptid = 0; if (n->param_decl.type_expr) { - ptid = sema_parse(sema, n->param_decl.type_expr); + return sema_parse(sema, n->param_decl.type_expr); } - spl_def_resolve(sema->type, n->resolved_def_id, ptid); - return ptid; - } break; - case SPL_AST_ATTR_ITEM: - vec_for(n->attr_item.expr_list, i) { sema_parse(sema, vec_at(n->attr_item.expr_list, i)); } - break; - case SPL_AST_ARGG_INIT_ITEM: { - if (n->aggregate_init_item.expr) { - sema_parse(sema, n->aggregate_init_item.expr); - } - } break; - case SPL_AST_IF_STATEMENT: { - if (!n->if_statement.expr) { - SPL_ERROR(&n->dbg, "if statement not have condition expr"); - return 0; - } - spl_type_id_t ct = sema_parse(sema, n->if_statement.expr); - if (!sema_coerce_for_bool(sema, ct)) { - SPL_ERROR(&n->dbg, "if condition must be bool"); - sema->error_count++; - } - sema_parse(sema, n->if_statement.if_block); - sema_parse(sema, n->if_statement.else_block); - } break; - case SPL_AST_IFVAR_STATEMENT: { - if (n->ifvar_statement.packed_expr) { - sema_parse(sema, n->ifvar_statement.packed_expr); - } - sema_parse(sema, n->ifvar_statement.if_block); - sema_parse(sema, n->ifvar_statement.else_block); - } break; - case SPL_AST_WHILE_STATEMENT: { - if (!n->while_statement.expr) { - SPL_ERROR(&n->dbg, "while statement not have condition expr"); - return 0; - } - spl_type_id_t ct = sema_parse(sema, n->while_statement.expr); - if (!sema_coerce_for_bool(sema, ct)) { - SPL_ERROR(&n->dbg, "while condition must be bool"); - sema->error_count++; - } - sema_parse(sema, n->while_statement.while_block); - } break; - case SPL_AST_LOOP_STATEMENT: { - sema_parse(sema, n->loop_statement.loop_block); - } break; - case SPL_AST_FOR_STATEMENT: { - sema_push_scope(sema); - vec_for(n->for_statement.expr_vec, i) { - spl_ast_node_ref_t eref = vec_at(n->for_statement.expr_vec, i); - spl_type_id_t stid = sema_parse(sema, eref); - spl_type_id_t etid = sema_for_elem_type(sema, stid); - if (i < vec_size(n->for_statement.ident_vec)) { - const char *vname = vec_at(n->for_statement.ident_vec, i); - spl_symbol_t symbol = {0}; - symbol.name = vname; - symbol.kind = SPL_SYMBOL_KIND_VAR; - symbol.node = spl_def_alloc(sema->type, SPL_DEF_VAR, vname, n->dbg, eref); - spl_def_resolve(sema->type, symbol.node, etid); - spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); - } - } - sema_parse(sema, n->for_statement.block); - sema_pop_scope(sema); - } break; - case SPL_AST_MATCH_STATEMENT: { - if (n->match_statement.expr) { - sema_parse(sema, n->match_statement.expr); - } - vec_for(n->match_statement.paced_exprs, i) { - sema_parse(sema, vec_at(n->match_statement.paced_exprs, i)); - } - sema_parse(sema, n->match_statement.match_block); - } break; - case SPL_AST_RET_STATEMENT: { - if (n->ret_statement.expr) { - spl_type_id_t tid = sema_parse(sema, n->ret_statement.expr); - if (sema_coerce(sema, sema->current_fn_ret_tid, tid) != sema->current_fn_ret_tid) { - SPL_ERROR(&n->dbg, "return type not match"); - sema->error_count += 1; - } - n->resolved_type_id = sema->current_fn_ret_tid; - } - } break; - case SPL_AST_BREAK_STATEMENT: - case SPL_AST_CONTINUE_STATEMENT: - case SPL_AST_DEFER_STATEMENT: { - vec_for(n->defer_statement.block_or_statement, i) { - sema_parse(sema, vec_at(n->defer_statement.block_or_statement, i)); - } - } break; - case SPL_AST_TRY_STATEMENT: - case SPL_AST_CATCH_STATEMENT: - case SPL_AST_ERRDEFER_STATEMEMT: - case SPL_AST_EXPR_STATEMENT: - break; - case SPL_AST_PACKED_EXPR: { - if (n->packed_expr.expr) - sema_parse(sema, n->packed_expr.expr); - } break; - case SPL_AST_ASSIGN_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - if (lt == 0) { - SPL_ERROR(&n->dbg, "assign target has no type"); - sema->error_count++; - break; - } - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - if (sema_coerce(sema, lt, rt) == 0) { - SPL_ERROR(&n->dbg, "assign type mismatch"); - sema->error_count++; - break; - } - n->resolved_type_id = lt; - return lt; + return 0; } - case SPL_AST_ASSIGN_ADD_EXPR: - case SPL_AST_ASSIGN_SUB_EXPR: - case SPL_AST_ASSIGN_MUL_EXPR: - case SPL_AST_ASSIGN_DIV_EXPR: - case SPL_AST_ASSIGN_MOD_EXPR: - case SPL_AST_ASSIGN_AND_EXPR: - case SPL_AST_ASSIGN_OR_EXPR: - case SPL_AST_ASSIGN_XOR_EXPR: - case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_RSHIFT_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - if (lt == 0) { - SPL_ERROR(&n->dbg, "assign target has no type"); - sema->error_count++; - break; - } - if (sema_coerce_balance(sema, lt, rt) != lt) { - SPL_ERROR(&n->dbg, "compound assign result would narrow or mismatch lhs type"); - sema->error_count++; - break; - } - n->resolved_type_id = lt; - return lt; - } - case SPL_AST_BOOL_OR_EXPR: - case SPL_AST_BOOL_AND_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - 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_ERROR(&n->dbg, "logical operands must be bool"); - sema->error_count++; - break; - } - spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); - n->resolved_type_id = bt; - return bt; - } - case SPL_AST_BIT_OR_EXPR: - case SPL_AST_BIT_XOR_EXPR: - case SPL_AST_BIT_AND_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - spl_type_id_t peer = sema_coerce_balance(sema, lt, rt); - spl_type_node_t *pn = spl_type_node(sema->type, peer); - if (!pn || pn->kind != SPL_TYPE_INT) { - SPL_ERROR(&n->dbg, "bitwise operands must be integers"); - sema->error_count++; - break; - } - n->resolved_type_id = peer; - return peer; - } - case SPL_AST_CMP_EQ_EXPR: - case SPL_AST_CMP_NE_EXPR: - case SPL_AST_CMP_LE_EXPR: - case SPL_AST_CMP_GE_EXPR: - case SPL_AST_CMP_LT_EXPR: - case SPL_AST_CMP_GT_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - if (sema_coerce_balance(sema, lt, rt) == 0) { - SPL_ERROR(&n->dbg, "comparison operands type mismatch"); - sema->error_count++; - break; - } - spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); - n->resolved_type_id = bt; - return bt; - } - case SPL_AST_RANGE_EXPR: { - if (n->op_expr.left) - sema_parse(sema, n->op_expr.left); - if (n->op_expr.right) - sema_parse(sema, n->op_expr.right); - spl_type_id_t i64 = spl_type_builder_int(sema->type, 64, true); - spl_type_id_t rt = spl_type_builder_range(sema->type, i64); - n->resolved_type_id = rt; - return rt; - } - case SPL_AST_LSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - 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_ERROR(&n->dbg, "shift operands must be integers"); - sema->error_count++; - break; - } - n->resolved_type_id = lt; - return lt; - } - case SPL_AST_ADD_EXPR: - case SPL_AST_SUB_EXPR: - case SPL_AST_MUL_EXPR: - case SPL_AST_DIV_EXPR: - case SPL_AST_MOD_EXPR: { - spl_type_id_t lt = sema_parse(sema, n->op_expr.left); - spl_type_id_t rt = sema_parse(sema, n->op_expr.right); - spl_type_node_t *ln = spl_type_node(sema->type, lt); - spl_type_node_t *rn = spl_type_node(sema->type, rt); - spl_type_id_t peer = sema_coerce_balance(sema, lt, rt); - spl_type_node_t *pn = spl_type_node(sema->type, peer); - if (!pn || (pn->kind != SPL_TYPE_INT && pn->kind != SPL_TYPE_FLOAT)) { - SPL_ERROR(&n->dbg, "arithmetic operands type mismatch"); - sema->error_count++; - break; - } - n->resolved_type_id = peer; - return peer; - } - case SPL_AST_MINUS_EXPR: { - spl_ast_node_t *op = spl_ast_node(sema->ast, n->prefix_expr.postfix_expr); - if (op && op->kind == SPL_AST_EXPR_INTEGER_LIT) { - spl_type_id_t ct = spl_type_builder_int(sema->type, 0, true); - n->resolved_type_id = ct; - return ct; - } - if (op && op->kind == SPL_AST_EXPR_FLOAT_LIT) { - spl_type_id_t ct = spl_type_builder_float(sema->type, 0); - n->resolved_type_id = ct; - return ct; - } - spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); - spl_type_node_t *tn = spl_type_node(sema->type, t); - if (!tn || (tn->kind != SPL_TYPE_INT && tn->kind != SPL_TYPE_FLOAT)) { - SPL_ERROR(&n->dbg, "unary minus requires numeric operand"); - sema->error_count++; - break; - } - n->resolved_type_id = t; - return t; - } - case SPL_AST_NOT_EXPR: { - spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); - spl_type_node_t *tn = spl_type_node(sema->type, t); - if (!tn || tn->kind != SPL_TYPE_BOOL) { - SPL_ERROR(&n->dbg, "`not` requires bool operand"); - sema->error_count++; - break; - } - spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); - n->resolved_type_id = bt; - return bt; - } - case SPL_AST_BIT_NOT_EXPR: { - spl_type_id_t t = sema_parse(sema, n->prefix_expr.postfix_expr); - spl_type_node_t *tn = spl_type_node(sema->type, t); - if (!tn || tn->kind != SPL_TYPE_INT) { - SPL_ERROR(&n->dbg, "bitnot requires integer operand"); - sema->error_count++; - break; - } - n->resolved_type_id = t; - return t; - } - case SPL_AST_ADDRESS_EXPR: - if (n->prefix_expr.postfix_expr) - sema_parse(sema, n->prefix_expr.postfix_expr); - break; - case SPL_AST_CALL_EXPR: { - spl_type_id_t fnt = sema_parse(sema, n->postfix_expr.primary_expr); - spl_type_node_t *fn = spl_type_node(sema->type, fnt); - if (!fn || fn->kind != SPL_TYPE_FN) { - SPL_ERROR(&n->dbg, "call target is not a function"); - sema->error_count++; - break; - } - // TODO type check - vec_for(n->postfix_expr.call_expr, i) { - spl_type_id_t at = sema_parse(sema, vec_at(n->postfix_expr.call_expr, i)); - if (sema_coerce(sema, vec_at(fn->fn_type.params, i), at) == 0) { - SPL_ERROR(&n->dbg, "call argument type mismatch"); - sema->error_count++; - } - } - n->resolved_type_id = fn->fn_type.ret; - return fn->fn_type.ret; - } - case SPL_AST_DEREF_EXPR: { - spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); - spl_type_node_t *bn = spl_type_node(sema->type, btid); - if (!bn || bn->kind != SPL_TYPE_PTR) { - SPL_ERROR(&n->dbg, "deref requires pointer"); - sema->error_count++; - break; - } - n->resolved_type_id = bn->ptr_pointee; - return bn->ptr_pointee; - } - case SPL_AST_FIELD_EXPR: { - spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); - spl_type_node_t *bn = spl_type_node(sema->type, btid); - spl_type_id_t agg_tid = btid; - if (bn && bn->kind == SPL_TYPE_PTR) - agg_tid = bn->ptr_pointee; /* 自动单层解引用 */ - spl_type_node_t *an = spl_type_node(sema->type, agg_tid); - const char *fname = n->postfix_expr.field_expr; - const spl_type_member_t *m = NULL; - if (an && (an->kind == SPL_TYPE_STRUCT || an->kind == SPL_TYPE_UNION)) - m = spl_type_agg_member(sema->type, agg_tid, fname); - if (!m) { - SPL_ERROR(&n->dbg, "no field `%s`", fname); - sema->error_count++; - break; - } - n->resolved_type_id = m->type_id; - return m->type_id; - } - case SPL_AST_INDEX_EXPR: { - spl_type_id_t btid = sema_parse(sema, n->postfix_expr.primary_expr); - if (n->postfix_expr.index_expr) - sema_parse(sema, n->postfix_expr.index_expr); - spl_type_node_t *bn = spl_type_node(sema->type, btid); - spl_type_id_t etid = 0; - if (bn) { - switch (bn->kind) { - case SPL_TYPE_SLICE: - etid = bn->slice_element; - break; - case SPL_TYPE_ARRAY: - etid = bn->array_type.element; - break; - case SPL_TYPE_PTR: - etid = bn->ptr_pointee; - break; - default: - break; - } - } - if (etid == 0) { - SPL_ERROR(&n->dbg, "index base must be slice/array/ptr"); - sema->error_count++; - break; - } - n->resolved_type_id = etid; - return etid; - } - case SPL_AST_SLICE_EXPR: - if (n->postfix_expr.primary_expr) - sema_parse(sema, n->postfix_expr.primary_expr); - if (n->postfix_expr.slice_expr.begin) - sema_parse(sema, n->postfix_expr.slice_expr.begin); - if (n->postfix_expr.slice_expr.end) - sema_parse(sema, n->postfix_expr.slice_expr.end); - break; - case SPL_AST_AS_EXPR: { - spl_type_id_t st = sema_parse(sema, n->postfix_expr.primary_expr); - spl_type_id_t tt = sema_parse(sema, n->postfix_expr.type_expr); - spl_type_node_t *sn = spl_type_node(sema->type, st); - if (tt == 0 || !sn || - (sn->kind != SPL_TYPE_INT && sn->kind != SPL_TYPE_FLOAT && sn->kind != SPL_TYPE_BOOL)) { - SPL_ERROR(&n->dbg, "invalid `as` cast"); - sema->error_count++; - break; - } - n->resolved_type_id = tt; - return tt; - } - case SPL_AST_EXPR_INTEGER_LIT: { - spl_type_id_t ct = spl_type_builder_int(sema->type, 0, true); + + case SPL_AST_EXPR_INT_LIT: { + spl_type_id_t ct = spl_type_make_int(sema->type, 0, true); n->resolved_type_id = ct; return ct; } case SPL_AST_EXPR_FLOAT_LIT: { - spl_type_id_t ct = spl_type_builder_float(sema->type, 0); + spl_type_id_t ct = spl_type_make_float(sema->type, 0); n->resolved_type_id = ct; return ct; } - case SPL_AST_EXPR_CHAR_LIT: - break; + case SPL_AST_EXPR_CHAR_LIT: { + spl_type_id_t u8 = spl_type_make_int(sema->type, 8, false); + n->resolved_type_id = u8; + return u8; + } case SPL_AST_EXPR_STRING_LIT: { - /* SPL.md: 字符串字面量 -> []u8 */ - spl_type_id_t u8 = spl_type_builder_int(sema->type, 8, false); - spl_type_id_t st = spl_type_builder_slice(sema->type, u8); - n->resolved_type_id = st; - return st; + 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; } - case SPL_AST_EXPR_NULL: { - spl_type_id_t nt = spl_type_builder_simple(sema->type, SPL_TYPE_NULL); - n->resolved_type_id = nt; - return nt; - } - case SPL_AST_EXPR_TRUE: - case SPL_AST_EXPR_FALSE: { - spl_type_id_t bt = spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); + case SPL_AST_EXPR_BOOL_LIT: { + spl_type_id_t bt = spl_type_make_bool(sema->type); n->resolved_type_id = bt; return bt; } - case SPL_AST_EXPR_UNDEFINED: { - spl_type_id_t ut = spl_type_builder_simple(sema->type, SPL_TYPE_UNDEFINED); - n->resolved_type_id = ut; - return ut; - } - case SPL_AST_EXPR_IDENT: { - spl_symbol_t symbol = {0}; - if (!spl_scope_find(sema->scope, n->primary_expr.ident, &symbol)) { - SPL_ERROR(&n->dbg, "can't find ident `%s`", n->primary_expr.ident); - sema->error_count++; - return 0; - } - Assert(symbol.node != 0); - n->resolved_def_id = symbol.node; - spl_def_node_t *d = spl_def_node(sema->type, symbol.node); - Assert(d != 0); - return d->type_id; - } - case SPL_AST_ARGGREGATE_INIT: { - const char *tname = n->primary_expr.aggregate_init.name; - if (!tname) { - SPL_ERROR(&n->dbg, "anonymous aggregate init TODO"); - sema->error_count++; - break; - } - spl_symbol_t sym = {0}; - if (!spl_scope_find(sema->scope, tname, &sym)) { - SPL_ERROR(&n->dbg, "aggregate init: unknown type `%s`", tname); - sema->error_count++; - break; - } - spl_def_node_t *d = spl_def_node(sema->type, sym.node); - spl_type_id_t tid = d ? d->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)) { - SPL_ERROR(&n->dbg, "aggregate init: `%s` is not a struct", tname); - sema->error_count++; - break; - } - usize got = 0; - vec_for(n->primary_expr.aggregate_init.expr, i) { - spl_ast_node_t *item = - spl_ast_node(sema->ast, vec_at(n->primary_expr.aggregate_init.expr, i)); - if (!item || item->kind != SPL_AST_ARGG_INIT_ITEM) - continue; - got++; - const char *fname = item->aggregate_init_item.ident; - spl_type_id_t etid = item->aggregate_init_item.expr - ? sema_parse(sema, item->aggregate_init_item.expr) - : 0; - const spl_type_member_t *m = spl_type_agg_member(sema->type, tid, fname); - if (!m) { - SPL_ERROR(&item->dbg, "aggregate init: no field `%s` in `%s`", fname, tname); - sema->error_count++; - continue; - } - if (sema_coerce(sema, m->type_id, etid) == 0) { - SPL_ERROR(&item->dbg, "aggregate init: field `%s` type mismatch", fname); - sema->error_count++; - } - } - if (tn->kind == SPL_TYPE_STRUCT && got != vec_size(tn->agg_members)) { - SPL_ERROR(&n->dbg, "aggregate init: field count mismatch (%zu/%zu)", got, - vec_size(tn->agg_members)); - sema->error_count++; - } - n->resolved_type_id = tid; - return tid; - } - case SPL_AST_EXPR_EXPR: { - spl_type_id_t t = sema_parse(sema, n->primary_expr.expr); + 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; } - case SPL_AST_ARRAY_LIT: - if (n->primary_expr.array_lit_expr.type_expr) - sema_parse(sema, n->primary_expr.array_lit_expr.type_expr); - vec_for(n->primary_expr.array_lit_expr.expr_list, i) { - sema_parse(sema, vec_at(n->primary_expr.array_lit_expr.expr_list, i)); + case SPL_AST_EXPR_UNDEFINED_LIT: { + spl_type_id_t t = spl_type_make_never(sema->type); + n->resolved_type_id = t; + return t; + } + case SPL_AST_EXPR_IDENT: { + const char *name = n->ident.name; + spl_symbol_t sym; + if (!spl_scope_find(sema->scope, name, &sym)) { + SPL_ERROR(&n->dbg, "undefined identifier `%s`", name); + sema->error_count++; + return 0; + } + if (sym.node == 0) { + SPL_ERROR(&n->dbg, "identifier `%s` has no definition", name); + sema->error_count++; + return 0; + } + n->resolved_def_id = sym.node; + spl_def_node_t *def = spl_def_node(sema->type, sym.node); + if (!def) { + SPL_ERROR(&n->dbg, "definition for `%s` not found", name); + sema->error_count++; + return 0; + } + return def->type_id; + } + + case SPL_AST_EXPR_UNARY: { + spl_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); + if (!tn) + return 0; + + switch (n->unary.op) { + case SPL_UNARY_OP_MINUS: + if (tn->kind != SPL_TYPE_INT && tn->kind != SPL_TYPE_FLOAT) { + SPL_ERROR(&n->dbg, "unary minus requires numeric operand"); + sema->error_count++; + return 0; + } + n->resolved_type_id = operand_tid; + return operand_tid; + case SPL_UNARY_OP_NOT: + if (tn->kind != SPL_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); + n->resolved_type_id = bt; + return bt; + } + case SPL_UNARY_OP_BIT_NOT: + if (tn->kind != SPL_TYPE_INT) { + SPL_ERROR(&n->dbg, "bitwise not requires integer operand"); + sema->error_count++; + return 0; + } + 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); + n->resolved_type_id = ptr_tid; + return ptr_tid; + } + default: + UNREACHABLE(); } break; - case SPL_AST_BUILTIN_EXPR: - vec_for(n->primary_expr.builtin_expr.expr_list, i) { - sema_parse(sema, vec_at(n->primary_expr.builtin_expr.expr_list, i)); + } + + 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_binary_op_t op = n->binary.op; + + switch (op) { + case SPL_OP_ASSIGN: + if (sema_coerce(sema, lt, rt) == 0) { + SPL_ERROR(&n->dbg, "assignment type mismatch"); + sema->error_count++; + return 0; + } + n->resolved_type_id = lt; + return lt; + + case SPL_OP_ASSIGN_ADD: + case SPL_OP_ASSIGN_SUB: + case SPL_OP_ASSIGN_MUL: + case SPL_OP_ASSIGN_DIV: + case SPL_OP_ASSIGN_MOD: + case SPL_OP_ASSIGN_AND: + case SPL_OP_ASSIGN_OR: + 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); + if (balanced == 0 || balanced != lt) { + SPL_ERROR(&n->dbg, "compound assignment type mismatch"); + sema->error_count++; + return 0; + } + n->resolved_type_id = lt; + return lt; } - break; - case SPL_AST_BLOCK_EXPR: - vec_for(n->primary_expr.block_expr, i) { - sema_parse(sema, vec_at(n->primary_expr.block_expr, i)); + + 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_ERROR(&n->dbg, "logical operands must be bool"); + sema->error_count++; + return 0; + } + spl_type_id_t bt = spl_type_make_bool(sema->type); + n->resolved_type_id = bt; + return bt; } - break; - case SPL_AST_BASE_TYPE_FN: - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - vec_for(n->type_expr.fn_type.param_list, i) { - sema_parse(sema, vec_at(n->type_expr.fn_type.param_list, i)); + + 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_ERROR(&n->dbg, "bitwise operands must be integers"); + sema->error_count++; + return 0; + } + n->resolved_type_id = bal; + return bal; } - if (n->type_expr.fn_type.type_expr) - sema_parse(sema, n->type_expr.fn_type.type_expr); - break; - case SPL_AST_BASE_TYPE_PATH: { - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - if (vec_size(n->type_expr.type_path.ident_vec) == 0) + + case SPL_OP_CMP_EQ: + case SPL_OP_CMP_NE: + case SPL_OP_CMP_LE: + case SPL_OP_CMP_GE: + case SPL_OP_CMP_LT: + case SPL_OP_CMP_GT: { + if (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); + 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_ERROR(&n->dbg, "shift operands must be integers"); + sema->error_count++; + return 0; + } + n->resolved_type_id = lt; + return lt; + } + + case SPL_OP_ADD: + case SPL_OP_SUB: + 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_ERROR(&n->dbg, "arithmetic operands type mismatch"); + sema->error_count++; + return 0; + } + n->resolved_type_id = bal; + return bal; + } + + case SPL_OP_RANGE: { + spl_type_id_t i64 = spl_type_make_int(sema->type, 64, true); + n->resolved_type_id = i64; + return i64; + } + + default: break; - const char *tname = vec_at(n->type_expr.type_path.ident_vec, 0); - if (vec_size(n->type_expr.type_path.ident_vec) == 1) { - spl_symbol_t sym = {0}; - if (spl_scope_find(sema->scope, tname, &sym)) { - spl_def_node_t *d = spl_def_node(sema->type, sym.node); - if (d && d->type_id) { - n->resolved_type_id = d->type_id; - return d->type_id; + } + break; + } + + 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_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++; + } 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++; } } - SPL_ERROR(&n->dbg, "type `%s` not found", tname); + } + spl_type_id_t ret_tid = fn->fn_type.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); + 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; + } + 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_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); + 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; + } + + 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); + 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; break; } - /* 多段命名空间路径(如 Str.Inner):TODO */ - SPL_ERROR(&n->dbg, "nested type path TODO"); - sema->error_count++; - 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; + 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; + } + (void)idx_tid; + n->resolved_type_id = elem_tid; + return elem_tid; } - case SPL_AST_TYPE_POINTER: { - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - spl_type_id_t ptid = 0; - if (n->type_expr.pointer_type.pointee) - ptid = sema_parse(sema, n->type_expr.pointer_type.pointee); - spl_type_id_t tid = spl_type_builder_ptr(sema->type, ptid); - n->resolved_type_id = tid; - return tid; + + case SPL_AST_EXPR_SLICE: { + spl_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); + 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; + } + } 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); + n->resolved_type_id = slice_tid; + return slice_tid; } - case SPL_AST_TYPE_ARRAY: { - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - spl_type_id_t etid = 0; - if (n->type_expr.array_type.element) - etid = sema_parse(sema, n->type_expr.array_type.element); - usize len = 0; - if (n->type_expr.array_type.size) { - spl_ast_node_t *sz = spl_ast_node(sema->ast, n->type_expr.array_type.size); - if (sz && sz->kind == SPL_AST_EXPR_INTEGER_LIT) { - len = (usize)sz->primary_expr.integer_expr; - } else { - sema_parse(sema, n->type_expr.array_type.size); + + 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); + if (!src_node) + return 0; + if (src_node->kind != SPL_TYPE_INT && src_node->kind != SPL_TYPE_FLOAT && + src_node->kind != SPL_TYPE_BOOL) { + SPL_ERROR(&n->dbg, "invalid cast from non-primitive type"); + sema->error_count++; + return 0; + } + n->resolved_type_id = dst_tid; + return dst_tid; + } + + case SPL_AST_EXPR_TUPLE: { + for (usize i = 0; i < vec_size(n->tuple.elems); ++i) { + sema_parse(sema, vec_at(n->tuple.elems, i)); + } + return 0; + } + + case SPL_AST_EXPR_ARRAY_LIT: { + spl_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)); + if (elem_tid == 0) + elem_tid = et; + else if (sema_coerce(sema, elem_tid, et) == 0) { + SPL_ERROR(&n->dbg, "array element type mismatch"); + sema->error_count++; } } - spl_type_id_t tid = spl_type_builder_array(sema->type, etid, len); - n->resolved_type_id = tid; - return tid; - } - case SPL_AST_TYPE_SLICE: { - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - spl_type_id_t etid = 0; - if (n->type_expr.slice_type.element) - etid = sema_parse(sema, n->type_expr.slice_type.element); - spl_type_id_t tid = spl_type_builder_slice(sema->type, etid); - n->resolved_type_id = tid; - return tid; - } - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_SHAPE: - case SPL_AST_TYPE_ENUM: - vec_for(n->type_expr.attr_list, i) { sema_parse(sema, vec_at(n->type_expr.attr_list, i)); } - vec_for(n->type_expr.aggregate_list, i) { - sema_parse(sema, vec_at(n->type_expr.aggregate_list, i)); + + usize len; + if (n->array_literal.is_underscore_len) { + len = vec_size(n->array_literal.elems); + } else { + len = + n->array_literal.has_len ? n->array_literal.len : vec_size(n->array_literal.elems); } - break; - case SPL_AST_TYPE_VOID: - return spl_type_builder_simple(sema->type, SPL_TYPE_VOID); - case SPL_AST_TYPE_BOOL: - return spl_type_builder_simple(sema->type, SPL_TYPE_BOOL); - case SPL_AST_TYPE_OPAQUE: + spl_type_id_t arr_tid = spl_type_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; + 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)); + if (elem_tid == 0) + elem_tid = et; + else if (sema_coerce(sema, elem_tid, et) == 0) { + SPL_ERROR(&n->dbg, "array element type mismatch"); + sema->error_count++; + } + } + usize len = vec_size(n->anon_array_literal.elems); + spl_type_id_t arr_tid = spl_type_make_array(sema->type, elem_tid, len); + n->resolved_type_id = arr_tid; + return arr_tid; + } + + case SPL_AST_EXPR_AGGREGATE_LIT: { + const char *type_name = n->aggregate_literal.name; + if (!type_name) { + SPL_ERROR(&n->dbg, "anonymous aggregate literal not supported yet"); + sema->error_count++; + return 0; + } + spl_symbol_t sym; + if (!spl_scope_find(sema->scope, type_name, &sym)) { + SPL_ERROR(&n->dbg, "unknown type `%s`", type_name); + sema->error_count++; + 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)) { + SPL_ERROR(&n->dbg, "`%s` is not a struct/union", type_name); + sema->error_count++; + return 0; + } + + for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { + spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i)); + if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) + continue; + + const char *fname = item->struct_init_item.name; + spl_type_id_t field_tid = 0; + if (item->struct_init_item.expr) { + field_tid = sema_parse(sema, item->struct_init_item.expr); + } + const spl_type_member_t *member = spl_type_agg_member(sema->type, tid, 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_ERROR(&item->dbg, "field `%s` type mismatch", fname); + sema->error_count++; + } + } + + n->resolved_type_id = tid; + return tid; + } + + case SPL_AST_EXPR_COMPTIME_CALL: + return 0; + + case SPL_AST_EXPR_BLOCK: { + for (usize i = 0; i < vec_size(n->block.stmts); ++i) { + sema_parse(sema, vec_at(n->block.stmts, i)); + } + if (n->block.tail_expr) { + return sema_parse(sema, n->block.tail_expr); + } + return 0; + } + + case SPL_AST_EXPR_IF: { + spl_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++; + } + sema_parse(sema, n->if_expr.then_block); + if (n->if_expr.else_branch) { + sema_parse(sema, n->if_expr.else_branch); + } + return 0; + } + + case SPL_AST_EXPR_IFVAR: { + sema_parse(sema, n->ifvar_expr.var_decl); + sema_parse(sema, n->ifvar_expr.then_block); + if (n->ifvar_expr.else_branch) { + sema_parse(sema, n->ifvar_expr.else_branch); + } + return 0; + } + + case SPL_AST_EXPR_WHILE: { + spl_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++; + } + sema_parse(sema, n->while_expr.body); + if (n->while_expr.else_branch) { + sema_parse(sema, n->while_expr.else_branch); + } + return 0; + } + + case SPL_AST_EXPR_LOOP: { + sema_parse(sema, n->loop_expr.body); + return 0; + } + + 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); + 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) { + const char *var_name = id_node->ident.name; + if (strcmp(var_name, "_") != 0) { + spl_symbol_t sym = {.name = var_name, .kind = SPL_SYMBOL_KIND_VAR}; + sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg, + vec_at(n->for_expr.idents, i)); + spl_def_resolve(sema->type, sym.node, elem_tid); + spl_scope_insert(sema->scope, sema->scope->current_scope, sym); + id_node->resolved_def_id = sym.node; + } + } + } + } + sema_parse(sema, n->for_expr.body); + if (n->for_expr.else_branch) { + sema_parse(sema, n->for_expr.else_branch); + } + sema_pop_scope(sema); + return 0; + } + + case SPL_AST_EXPR_MATCH: { + sema_parse(sema, n->match_expr.matched_expr); + for (usize i = 0; i < vec_size(n->match_expr.arms); ++i) { + spl_ast_node_t *arm = spl_ast_node(sema->ast, vec_at(n->match_expr.arms, i)); + if (arm && arm->kind == SPL_AST_MATCH_ARM) { + sema_parse(sema, arm->match_arm.pattern); + sema_parse(sema, arm->match_arm.body); + } + } + return 0; + } + + case SPL_AST_EXPR_FN_TYPE: { + spl_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)); + vec_free(params); + n->resolved_type_id = fn_tid; + return fn_tid; + } + + 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); + 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); + sema->error_count++; + return 0; + } + spl_def_node_t *def = spl_def_node(sema->type, sym.node); + if (!def) + return 0; + n->resolved_type_id = def->type_id; + return def->type_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); + 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); + 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); + 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); + n->resolved_type_id = slice_tid; + return slice_tid; + } + + case SPL_AST_TYPE_FN: { + spl_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)); + vec_free(params); + n->resolved_type_id = fn_tid; + return fn_tid; + } + + 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); + n->resolved_type_id = unit; + return unit; + } + if (count == 1) { + 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 + 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); + } + 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; + } + + case SPL_AST_TYPE_AGGREGATE: { + return 0; + } + + case SPL_AST_TYPE_COMPTIME_CALL: + return 0; + + case SPL_AST_STATEMENT_RET: { + if (n->statement_ret.expr) { + spl_type_id_t ret_tid = sema_parse(sema, n->statement_ret.expr); + if (sema->current_fn_ret_tid != 0 && + sema_coerce(sema, sema->current_fn_ret_tid, ret_tid) == 0) { + SPL_ERROR(&n->dbg, "return type mismatch"); + sema->error_count++; + } + } + return 0; + } + + case SPL_AST_STATEMENT_BREAK: + case SPL_AST_STATEMENT_CONTINUE: + return 0; + + case SPL_AST_STATEMENT_DEFER: + if (n->statement_defer.body) { + sema_parse(sema, n->statement_defer.body); + } + return 0; + + case SPL_AST_STATEMENT_COMPTIME: + if (n->statement_comptime.body) { + sema_parse(sema, n->statement_comptime.body); + } + return 0; + + case SPL_AST_STATEMENT_DECL: + if (n->statement_decl.decl) { + sema_parse(sema, n->statement_decl.decl); + } + return 0; + + case SPL_AST_STATEMENT_EXPR: + if (n->statement_expr.expr) { + sema_parse(sema, n->statement_expr.expr); + } + return 0; + + default: return 0; - case SPL_AST_TYPE_I8: - return spl_type_builder_int(sema->type, 8, true); - case SPL_AST_TYPE_U8: - return spl_type_builder_int(sema->type, 8, false); - case SPL_AST_TYPE_I16: - return spl_type_builder_int(sema->type, 16, true); - case SPL_AST_TYPE_U16: - return spl_type_builder_int(sema->type, 16, false); - case SPL_AST_TYPE_I32: - return spl_type_builder_int(sema->type, 32, true); - case SPL_AST_TYPE_U32: - return spl_type_builder_int(sema->type, 32, false); - case SPL_AST_TYPE_I64: - return spl_type_builder_int(sema->type, 64, true); - case SPL_AST_TYPE_U64: - return spl_type_builder_int(sema->type, 64, false); - case SPL_AST_TYPE_ISIZE: - return spl_type_builder_int(sema->type, sizeof(void *) * 8, true); /* FIXME */ - case SPL_AST_TYPE_USIZE: - return spl_type_builder_int(sema->type, sizeof(void *) * 8, false); /* FIXME */ - case SPL_AST_TYPE__F32: - return spl_type_builder_float(sema->type, 32); - case SPL_AST_TYPE__F64: - return spl_type_builder_float(sema->type, 64); - case SPL_AST_TYPE_ANY: - case SPL_AST_TYPE_IDENT: - break; - case SPL_AST_COUNT: - UNREACHABLE(); - break; } return 0; } @@ -1081,6 +1150,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->root = (spl_symbol_t){0}; + sema->store_scope = 0; } void spl_sema_drop(spl_sema_t *sema) { (void)sema; } @@ -1089,40 +1159,38 @@ void spl_sema_run(spl_sema_t *sema) { if (!sema->ast || !sema->ast->root) return; - spl_ast_node_t *ast_node = spl_ast_node(sema->ast, sema->ast->root); - Assert(ast_node != NULL && ast_node->kind == SPL_AST_CONTAINER_MEMBERS); + 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); - // 第一趟 实现顺序无关地相互引用 - sema_collect(sema, sema->ast->root); - - // 第二趟 正式解析 - sema_parse(sema, sema->ast->root); + sema_collect(sema, root->root.members); + sema_parse(sema, root->root.members); } void spl_sema_dump(spl_sema_t *sema) { printf("Scopes:\n"); - vec_for(sema->scope->scopes, i) { + for (usize i = 0; i < vec_size(sema->scope->scopes); ++i) { if (i == 0) continue; - 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) { - spl_symbol_t *symbol = &unsafe_map_at(scope.symbols, j).val; - printf(" %s -> def`%s`#%zu\n", unsafe_map_at(scope.symbols, j).key, symbol->name, + 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) { + spl_symbol_t *symbol = &unsafe_map_at(scope->symbols, j).val; + printf(" %s -> def`%s`#%zu\n", unsafe_map_at(scope->symbols, j).key, symbol->name, symbol->node); } } printf("TypeTable:\n"); - vec_for(sema->type->type_table, i) { - printf(" id#%zu type=", i); + for (usize i = 0; i < vec_size(sema->type->type_table); ++i) { + printf(" id#%zu ", i); spl_type_pure_dump(sema->type, i); printf("\n"); } printf("DefTable:\n"); - vec_for(sema->type->def_table, i) { + for (usize i = 0; i < vec_size(sema->type->def_table); ++i) { printf(" def#%zu ", i); spl_type_def_dump(sema->type, i); - spl_def_node_t *d = spl_def_node(sema->type, i); printf("\n"); } -} +} \ No newline at end of file diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 951f206..239b86f 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -1,11 +1,17 @@ #include "spl_type.h" static usize spl_type_hash(spl_type_node_t n) { - usize hash = n.kind << 20; + usize hash = n.kind << 20; // FIXME least i32 switch (n.kind) { case SPL_TYPE_ERROR: - case SPL_TYPE_VOID: + case SPL_TYPE_UNIT: + case SPL_TYPE_ANY: + case SPL_TYPE_NEVER: + case SPL_TYPE_INFER: + case SPL_TYPE_FORALL: + case SPL_TYPE_EXISTS: case SPL_TYPE_BOOL: + break; case SPL_TYPE_INT: hash += n.int_type.bits + n.int_type.is_signed; break; @@ -44,8 +50,14 @@ static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; switch (n1.kind) { case SPL_TYPE_ERROR: - case SPL_TYPE_VOID: + case SPL_TYPE_UNIT: + case SPL_TYPE_ANY: + case SPL_TYPE_NEVER: + case SPL_TYPE_INFER: + case SPL_TYPE_FORALL: + case SPL_TYPE_EXISTS: case SPL_TYPE_BOOL: + break; case SPL_TYPE_INT: if (n1.int_type.bits != n2.int_type.bits) return 1; @@ -138,6 +150,45 @@ spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *tn) { return 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; + if (sub == super) + return true; + + spl_type_node_t *nsub = spl_type_node(type, sub); + spl_type_node_t *nsuper = spl_type_node(type, super); + if (!nsub || !nsuper) + return false; + + // never 是任何类型的子类型 bottom + if (nsub->kind == SPL_TYPE_NEVER) + return true; + // 任何类型是 any 的子类型 top + if (nsuper->kind == SPL_TYPE_ANY) + return true; + + // 处理 comptime_int / comptime_float 到具体数值类型 + 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; + } + + 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; +} + 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); @@ -172,12 +223,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; 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.int_type.bits = bits; tn.int_type.is_signed = is_signed; return spl_type_node_push(type, &tn); @@ -186,6 +239,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.float_type.bits = bits; return spl_type_node_push(type, &tn); } @@ -193,6 +247,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.ptr_type.pointee = pointee; return spl_type_node_push(type, &tn); } @@ -200,6 +255,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.array_type.element = element; tn.array_type.len = len; return spl_type_node_push(type, &tn); @@ -209,6 +265,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; vec_init(tn.fn_type.params); for (usize i = 0; i < nparams; i++) { vec_push(tn.fn_type.params, params[i]); @@ -222,6 +279,7 @@ 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; if (tk == SPL_TYPE_ENUM) { @@ -233,6 +291,134 @@ spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, 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; +} + +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_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_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_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_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_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_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_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_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_type_id_t spl_type_make_slice(spl_type_t *type, spl_type_id_t elem) { + // 底层构造 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_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_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; + 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; + return id; +} + spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { if (!name || !*name) return 0; @@ -241,7 +427,7 @@ spl_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { if (strcmp(name, "bool") == 0) return spl_type_builder_simple(type, SPL_TYPE_BOOL); if (strcmp(name, "void") == 0) - return spl_type_builder_simple(type, SPL_TYPE_VOID); + return spl_type_builder_simple(type, SPL_TYPE_UNIT); if (strcmp(name, "isize") == 0) return spl_type_builder_int(type, sizeof(void *) * 8, true); if (strcmp(name, "usize") == 0) @@ -273,43 +459,6 @@ spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id) { return def_node->type_id; } -spl_def_id_t spl_def_builder_void(spl_type_t *type) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_bool(spl_type_t *type) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_int(spl_type_t *type, usize bits, int is_signed) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_float(spl_type_t *type, usize bits) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_ptr(spl_type_t *type, spl_def_id_t pointee) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_array(spl_type_t *type, spl_def_id_t element, usize len) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_slice(spl_type_t *type, spl_type_id_t element) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_range(spl_type_t *type) { - TODO(); - return 0; -} -spl_def_id_t spl_def_builder_fn(spl_type_t *type) { - TODO(); - return 0; -} - 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}; @@ -342,19 +491,6 @@ void spl_type_init(spl_type_t *type) { 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}); - - // spl_type_builder_simple(type, SPL_TYPE_VOID); - // spl_type_builder_simple(type, SPL_TYPE_BOOL); - // spl_type_builder_int(type, 8, false); - // spl_type_builder_int(type, 16, false); - // spl_type_builder_int(type, 32, false); - // spl_type_builder_int(type, 64, false); - // spl_type_builder_int(type, 8, true); - // spl_type_builder_int(type, 16, true); - // spl_type_builder_int(type, 32, true); - // spl_type_builder_int(type, 64, true); - // spl_type_builder_float(type, 32); - // spl_type_builder_float(type, 64); } void spl_type_drop(spl_type_t *type) { @@ -402,8 +538,21 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { case SPL_TYPE_ERROR: printf("error"); break; - case SPL_TYPE_VOID: - printf("void"); + case SPL_TYPE_UNIT: + printf("unit"); + break; + case SPL_TYPE_ANY: + printf("any"); + break; + case SPL_TYPE_NEVER: + printf("never"); + break; + case SPL_TYPE_INFER: + printf("infer"); + break; + case SPL_TYPE_FORALL: + case SPL_TYPE_EXISTS: + TODO(); break; case SPL_TYPE_BOOL: printf("bool"); @@ -437,10 +586,13 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { 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; diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 69b2bb2..2a2d239 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -11,7 +11,10 @@ typedef VEC(spl_def_id_t) spl_def_id_vec_t; typedef enum { SPL_TYPE_ERROR, - SPL_TYPE_VOID, + SPL_TYPE_NEVER, // bottom type + SPL_TYPE_ANY, // top type + SPL_TYPE_INFER, // auto type + SPL_TYPE_UNIT, SPL_TYPE_BOOL, SPL_TYPE_INT, SPL_TYPE_FLOAT, @@ -20,10 +23,20 @@ typedef enum { SPL_TYPE_STRUCT, SPL_TYPE_UNION, SPL_TYPE_ENUM, - SPL_TYPE_SHAPE, SPL_TYPE_FN, + SPL_TYPE_FORALL, // TODO delete + SPL_TYPE_EXISTS, // TODO delete + 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, @@ -44,6 +57,7 @@ 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 { @@ -63,11 +77,14 @@ typedef struct { struct { spl_type_member_vec_t variants; spl_type_id_t tag_type; - } agg_type; // adt record aggregate + } agg_type; // adt record struct { spl_type_id_vec_t params; spl_type_id_t ret; } fn_type; + struct { + // TODO + } shape_type; }; } spl_type_node_t; typedef VEC(spl_type_node_t) spl_type_node_vec_t; @@ -114,6 +131,9 @@ void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); spl_type_node_t *spl_type_node(const spl_type_t *type, spl_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_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); @@ -134,17 +154,29 @@ 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_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_def_id_t spl_def_builder_void(spl_type_t *type); -spl_def_id_t spl_def_builder_bool(spl_type_t *type); -spl_def_id_t spl_def_builder_int(spl_type_t *type, usize bits, int is_signed); -spl_def_id_t spl_def_builder_float(spl_type_t *type, usize bits); -spl_def_id_t spl_def_builder_ptr(spl_type_t *type, spl_def_id_t pointee); -spl_def_id_t spl_def_builder_array(spl_type_t *type, spl_def_id_t element, usize len); -spl_def_id_t spl_def_builder_slice(spl_type_t *type, spl_type_id_t element); -spl_def_id_t spl_def_builder_range(spl_type_t *type); -spl_def_id_t spl_def_builder_fn(spl_type_t *type); #endif /* __SPL_TYPE_H__ */ diff --git a/stage1/splc0.c b/stage1/splc0.c index 390499c..eff6c12 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -91,25 +91,25 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, // memory leak return 0; } - // spl_sema_t sema; - // spl_type_t type; - // spl_scope_t scope; - // spl_type_init(&type); - // spl_scope_init(&scope); - // spl_sema_init(&sema, &ast, &type, &scope); - // sema.ast = * - // spl_sema_run(&sema); - // if (sema.error_count) { - // printf("sema errors=%d, no output\n", sema.error_count); - // // memory leak - // return 1; - // } - // if (dump == DUMP_SEMA) { - // spl_sema_dump(&sema); - // spl_ast_dump(&ast, ast.root); - // // memory leak - // return 0; - // } + spl_sema_t sema; + spl_type_t type; + spl_scope_t scope; + spl_type_init(&type); + spl_scope_init(&scope); + spl_sema_init(&sema, &ast, &type, &scope); + sema.ast = * + spl_sema_run(&sema); + if (sema.error_count) { + printf("sema errors=%d, no output\n", sema.error_count); + // memory leak + return 1; + } + if (dump == DUMP_SEMA) { + spl_sema_dump(&sema); + spl_ast_dump(&ast, ast.root); + // memory leak + return 0; + } // spl_ast2ir_t a2ir; // spl_ir_builder_t ir_builder;