diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index b286ffb..4018c75 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -91,7 +91,7 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const spl_ast_node_t n = {0}; n.kind = kind; n.resolved_def_id = 0; - n.resolved_type_id = 0; + n.resolved_lang_tid = 0; if (tok) { n.dbg.dbg_name = spl_ast_kind_name(kind); n.dbg.fname = tok->fname; diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index 1288d56..889b6e7 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -150,8 +150,10 @@ typedef VEC(spl_ast_node_ref_t) spl_ast_node_ref_vec_t; struct spl_ast_node { spl_ast_node_kind_t kind; spl_dbg_node_t dbg; + usize resolved_def_id; - usize resolved_type_id; + usize resolved_lang_tid; + usize expected_lang_tid; union { /* SPL_AST_ROOT */ diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index bc7dab3..b0bb4aa 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -8,11 +8,8 @@ static spl_type_id_t to_ir_type(spl_ast2ir_t *a, spl_lang_type_id_t lang) { } static spl_lang_type_id_t node_lang(spl_ast2ir_t *a, spl_ast_node_t *n) { - if (!n) - return 0; - if (n->kind == SPL_AST_EXPR_IDENT) - return spl_def_get_lang_id(a->sema->type, n->resolved_def_id); - return n->resolved_type_id; + (void)a; + return n ? n->resolved_lang_tid : 0; } static spl_type_id_t node_ir(spl_ast2ir_t *a, spl_ast_node_t *n) { @@ -30,27 +27,48 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref); static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref); static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n); static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref); -static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n); -static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in); +static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n); +static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref); +static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt, + spl_ir_node_ref_t v); + +static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in, + spl_ast_node_ref_vec_t *args); static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in); static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n); -static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in) { +static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in, + spl_ast_node_ref_vec_t *args) { switch (in) { case SPL_INTRIN_SIZEOF: { - spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0)); + spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0)); return spl_ir_builder_type_sizeof(a->ir, node_ir(a, arg)); } case SPL_INTRIN_ALIGNOF: { - spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(n->call.args, 0)); + spl_ast_node_t *arg = spl_ast_node(a->sema->ast, vec_at(*args, 0)); return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg)); } case SPL_INTRIN_ASSERT: { - /* 目前 SEMA 只做类型检查,emit 阶段留空, - @assert 展开需待 control.trap 语义明确后再实现 */ + spl_ir_node_ref_t cond = emit_expr(a, vec_at(*args, 0)); + if (!cond) + return 0; + + spl_lang_type_id_t b = spl_lang_make_bool(a->sema->type); + spl_ir_node_ref_t notc = spl_ir_builder_arith_not(a->ir, to_ir_type(a, b), cond); + spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, notc); + spl_ir_builder_block_end(a->ir); + + usize trap_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_builder_control_trap(a->ir); + spl_ir_builder_block_end(a->ir); + + usize cont_blk = spl_ir_builder_block_begin(a->ir); + spl_ir_builder_control_br_fixup(a->ir, br, trap_blk, cont_blk); return 0; } + case SPL_INTRIN_BREAKPOINT: + return spl_ir_builder_dbg_breakpoint(a->ir); default: UNREACHABLE(); } @@ -198,7 +216,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { } static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) { - spl_ir_node_ref_t v = emit_expr(a, n->cast.expr); + spl_ir_node_ref_t v = emit_expr_raw(a, n->cast.expr); if (!v) return 0; spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr); @@ -238,6 +256,28 @@ static spl_ir_node_ref_t emit_cast(spl_ast2ir_t *a, spl_ast_node_t *n) { } static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { + spl_ir_node_ref_t val = emit_expr_raw(a, ref); + if (!val) + return 0; + + spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + if (!n || n->expected_lang_tid == 0) + return val; + + spl_lang_type_id_t from = n->resolved_lang_tid; + spl_lang_type_id_t to = n->expected_lang_tid; + if (!from || from == to) + return val; + + spl_type_id_t from_ir = to_ir_type(a, from); + spl_type_id_t to_ir = to_ir_type(a, to); + if (!from_ir || !to_ir || from_ir == to_ir) + return val; + + return emit_implicit_cast(a, from_ir, to_ir, val); +} + +static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); if (!n) return 0; @@ -396,7 +436,7 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (callee && callee->kind == SPL_AST_EXPR_IDENT) { spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name); if (in != SPL_INTRIN_NONE) - return ast2ir_intrin_call(a, n, in); + return ast2ir_intrin_call(a, n, in, &n->call.args); } spl_ir_node_ref_t fn = emit_expr(a, n->call.callee); @@ -573,9 +613,12 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { spl_ir_builder_agg_construct_field(a->ir, node, len); return node; } - case SPL_AST_EXPR_COMPTIME_CALL: - // TODO - return 0; + case SPL_AST_EXPR_COMPTIME_CALL: { + spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); + if (in == SPL_INTRIN_NONE) + return 0; + return ast2ir_intrin_call(a, n, in, &n->comptime_call.args); + } default: TODO(); return 0; @@ -959,6 +1002,42 @@ static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { } } +static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_type_id_t ft, spl_type_id_t tt, + spl_ir_node_ref_t v) { + if (!ft || !tt || ft == tt) + return v; + spl_type_node_t *fs = spl_type_node(a->sema->type, ft); + spl_type_node_t *ts = spl_type_node(a->sema->type, tt); + if (!fs || !ts) + return v; + + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_INT) { + if (fs->int_type.bits == ts->int_type.bits) + return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); + if (fs->int_type.bits > ts->int_type.bits) + return spl_ir_builder_cast_trunc(a->ir, ft, tt, v); + if (fs->int_type.is_signed) + return spl_ir_builder_cast_sext(a->ir, ft, tt, v); + return spl_ir_builder_cast_zext(a->ir, ft, tt, v); + } + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_FLOAT) + return spl_ir_builder_case_int2float(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_case_float2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_FLOAT && ts->kind == SPL_TYPE_FLOAT) { + if (fs->float_type.bits > ts->float_type.bits) + return spl_ir_builder_cast_ftrunc(a->ir, ft, tt, v); + return spl_ir_builder_cast_fext(a->ir, ft, tt, v); + } + if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_INT) + return spl_ir_builder_cast_ptr2int(a->ir, ft, tt, v); + if (fs->kind == SPL_TYPE_INT && ts->kind == SPL_TYPE_PTR) + return spl_ir_builder_cast_int2ptr(a->ir, ft, tt, v); + return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); +} + static usize spl_int_map_hash(usize k) { return MAP_HASH_INT(k); } static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } diff --git a/stage1/spl_intrin.c b/stage1/spl_intrin.c index f5f637d..0784bbb 100644 --- a/stage1/spl_intrin.c +++ b/stage1/spl_intrin.c @@ -8,6 +8,8 @@ static const spl_intrin_info_t g_intrin_table[] = { SPL_INTRIN_RESULT_USIZE}, [SPL_INTRIN_ASSERT] = {"@assert", SPL_INTRIN_ASSERT, SPL_INTRIN_FORM_CALL, 1, 2, SPL_INTRIN_RESULT_UNIT}, + [SPL_INTRIN_BREAKPOINT] = {"@breakpoint", SPL_INTRIN_BREAKPOINT, SPL_INTRIN_FORM_CALL, 0, 0, + SPL_INTRIN_RESULT_UNIT}, [SPL_INTRIN_LEN] = {"len", SPL_INTRIN_LEN, SPL_INTRIN_FORM_FIELD, 0, 0, SPL_INTRIN_RESULT_USIZE}, }; diff --git a/stage1/spl_intrin.h b/stage1/spl_intrin.h index 009e5d3..70f292b 100644 --- a/stage1/spl_intrin.h +++ b/stage1/spl_intrin.h @@ -9,6 +9,7 @@ typedef enum { SPL_INTRIN_SIZEOF, SPL_INTRIN_ALIGNOF, SPL_INTRIN_ASSERT, + SPL_INTRIN_BREAKPOINT, SPL_INTRIN_LEN, } spl_intrin_t; diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index d86ac1d..d6dd85c 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -315,12 +315,16 @@ static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t k spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); n->kind = kind; n->dbg = b->dbg; - if (b->current_block < vec_size(b->blocks)) { - vec_at(b->blocks, b->current_block) = ref; - } else { + + if (b->current_block >= vec_size(b->blocks)) { Panic("unknown bblock"); return 0; } + + spl_ir_node_ref_t *slot = &vec_at(b->blocks, b->current_block); + if (*slot == 0) + *slot = ref; + return ref; } @@ -378,7 +382,7 @@ void spl_ir_builder_fn_end(spl_ir_builder_t *b) { target = vec_at(b->blocks, fx->block); } if (target == 0) { - Panic("unknown reloc target bblock"); + Panic("reloc to empty/unknown bblock #%zu", fx->block); } switch (fx->slot) { case SPL_IR_FIX_BR_TRUE: @@ -411,6 +415,10 @@ void spl_ir_builder_block_end(spl_ir_builder_t *b) { if (!b->terminated) { Panic("bblock must be end of terminated"); } + if (b->current_block != 0 && b->current_block < vec_size(b->blocks) && + vec_at(b->blocks, b->current_block) == 0) { + Panic("bblock #%zu is empty (no entry node emitted)", b->current_block); + } } #define X(name, kind) \ @@ -769,7 +777,9 @@ spl_ir_node_ref_t spl_ir_builder_control_ret(spl_ir_builder_t *b, spl_type_id_t } spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b) { - return builder_alloc_node(b, SPL_IR_CONTROL_UNREACHABLE); + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_CONTROL_UNREACHABLE); + b->terminated = true; + return ref; } spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) { diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 0cc3ee6..f63d9b7 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -54,9 +54,47 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { } static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref); -static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in); +static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref); +static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, + spl_lang_type_id_t expected); +static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in, + spl_ast_node_ref_vec_t *args); static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in); +static bool sema_is_infer(spl_sema_t *sema, spl_lang_type_id_t tid) { + spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid); + return n && n->kind == SPL_LANG_TYPE_INFER; +} + +static spl_lang_type_id_t sema_lang_from_ir(spl_sema_t *sema, spl_type_id_t ir) { + 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 == ir) + return i; + } + return 0; +} + +static bool sema_is_literal(spl_ast_node_t *n) { + switch (n->kind) { + case SPL_AST_EXPR_INT_LIT: + case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_EXPR_CHAR_LIT: + case SPL_AST_EXPR_STRING_LIT: + case SPL_AST_EXPR_BOOL_LIT: + case SPL_AST_EXPR_NULL_LIT: + case SPL_AST_EXPR_UNDEFINED_LIT: + return true; + default: + return false; + } +} + +static bool sema_is_numeric(spl_sema_t *sema, spl_lang_type_id_t tid) { + spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid); + return n && (n->kind == SPL_LANG_TYPE_INT || n->kind == SPL_LANG_TYPE_FLOAT); +} + static inline void sema_push_scope(spl_sema_t *sema) { spl_scope_id_t new_scope = spl_scope_alloc(sema->scope); sema->store_scope = sema->scope->current_scope; @@ -177,10 +215,10 @@ static void sema_collect(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); -static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in) { +static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in, + spl_ast_node_ref_vec_t *args) { const spl_intrin_info_t *info = spl_intrin_info(in); - usize nargs = vec_size(n->call.args); - + usize nargs = vec_size(*args); if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) { SPL_ERROR(&n->dbg, "`%s` expects %d..%d args, got %zu", info->name, info->min_args, info->max_args, nargs); @@ -191,27 +229,14 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, switch (in) { case SPL_INTRIN_SIZEOF: case SPL_INTRIN_ALIGNOF: { - spl_ast_node_ref_t arg_ref = vec_at(n->call.args, 0); - spl_ast_node_t *arg = spl_ast_node(sema->ast, arg_ref); - if (!arg || !(arg->kind == SPL_AST_TYPE_PATH || arg->kind == SPL_AST_TYPE_POINTER || - arg->kind == SPL_AST_TYPE_ARRAY || arg->kind == SPL_AST_TYPE_SLICE || - arg->kind == SPL_AST_TYPE_FN || arg->kind == SPL_AST_TYPE_PAREN)) { - SPL_ERROR(&n->dbg, "`%s` expects a type argument", info->name); - sema->error_count++; - return 0; - } - sema_parse(sema, arg_ref); + sema_infer(sema, vec_at(*args, 0)); /* 求类型表达式的值 */ return spl_lang_make_int(sema->type, sizeof(void *) * 8, 0); } case SPL_INTRIN_ASSERT: { - spl_lang_type_id_t cond = sema_parse(sema, vec_at(n->call.args, 0)); - spl_lang_type_id_t b = spl_lang_make_bool(sema->type); - if (spl_lang_type_coerce_to(sema->type, b, cond) == 0) { - SPL_ERROR(&n->dbg, "`@assert` condition must be bool"); - sema->error_count++; - } + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, vec_at(*args, 0), bt); if (nargs == 2) - sema_parse(sema, vec_at(n->call.args, 1)); + sema_infer(sema, vec_at(*args, 1)); return spl_lang_make_unit(sema->type); } default: @@ -236,6 +261,1180 @@ static spl_lang_type_id_t sema_intrin_field(spl_sema_t *sema, spl_ast_node_t *n, return 0; } +static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, + spl_lang_type_id_t expected) { + if (!ref || !expected) + return 0; + spl_ast_node_t *n = spl_ast_node(sema->ast, ref); + if (!n) + return 0; + + /* ============ 类 1:构造性节点 —— 就地定型为 expected ============ */ + switch (n->kind) { + + case SPL_AST_EXPR_UNARY: { + if (n->unary.op == SPL_UNARY_OP_ADDRESS) + return sema_infer(sema, ref); /* &x 没有"被 check 到某类型"的语义 */ + if (!sema_check(sema, n->unary.operand, expected)) + return 0; + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + + case SPL_AST_EXPR_BINARY: { + spl_binary_op_t op = n->binary.op; + + /* 赋值 / 复合赋值:右侧 check 到左侧类型 */ + if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) { + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + if (!lt) + return 0; + if (!sema_check(sema, n->binary.right, lt)) + return 0; + n->resolved_lang_tid = lt; + n->expected_lang_tid = 0; + return lt; + } + + /* 逻辑运算:两侧 check 到 bool */ + if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + if (!sema_check(sema, n->binary.left, bt)) + return 0; + if (!sema_check(sema, n->binary.right, bt)) + return 0; + n->resolved_lang_tid = bt; + n->expected_lang_tid = 0; + return bt; + } + + /* 比较:数值类型允许异构比较;其他走 balance */ + if (op == SPL_OP_CMP_EQ || op == SPL_OP_CMP_NE || op == SPL_OP_CMP_LT || + op == SPL_OP_CMP_LE || op == SPL_OP_CMP_GT || op == SPL_OP_CMP_GE) { + + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + spl_lang_type_id_t rt = sema_infer(sema, n->binary.right); + if (!lt || !rt) + return 0; + + 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 l_num = ln && (ln->kind == SPL_LANG_TYPE_INT || ln->kind == SPL_LANG_TYPE_FLOAT); + bool r_num = rn && (rn->kind == SPL_LANG_TYPE_INT || rn->kind == SPL_LANG_TYPE_FLOAT); + + if (l_num && r_num) { + /* 数值比较:允许异构。仅当一侧 comptime 时把另一侧具体类型下推 */ + if (ln->kind == SPL_LANG_TYPE_INT && rn->kind == SPL_LANG_TYPE_INT) { + spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id); + spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id); + if (lir && lir->int_type.bits == 0) + sema_check(sema, n->binary.left, rt); + else if (rir && rir->int_type.bits == 0) + sema_check(sema, n->binary.right, lt); + } else if (ln->kind == SPL_LANG_TYPE_FLOAT && rn->kind == SPL_LANG_TYPE_FLOAT) { + spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id); + spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id); + if (lir && lir->float_type.bits == 0) + sema_check(sema, n->binary.left, rt); + else if (rir && rir->float_type.bits == 0) + sema_check(sema, n->binary.right, lt); + } + } else { + /* 非数值:要求 coerce 到共同类型 */ + spl_lang_type_id_t common = + (lt == rt) ? lt : spl_lang_type_balance(sema->type, lt, rt); + if (!common) { + SPL_ERROR(&n->dbg, "comparison operands type mismatch"); + sema->error_count++; + return 0; + } + if (!sema_check(sema, n->binary.left, common)) + return 0; + if (!sema_check(sema, n->binary.right, common)) + return 0; + } + + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + n->resolved_lang_tid = bt; + n->expected_lang_tid = 0; + return bt; + } + + /* 算术 / 位 / 移位:两侧 check 到 expected */ + if (!sema_check(sema, n->binary.left, expected)) + return 0; + if (!sema_check(sema, n->binary.right, expected)) + return 0; + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + + case SPL_AST_EXPR_ARRAY_LIT: { + spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected); + if (en && en->kind == SPL_LANG_TYPE_ARRAY) { + spl_lang_type_id_t et = en->extra.elem; + for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) + if (!sema_check(sema, vec_at(n->array_literal.elems, i), et)) + return 0; + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + break; /* 非数组 expected:退回通用逻辑 */ + } + + case SPL_AST_EXPR_AGGREGATE_LIT: { + spl_lang_type_node_t *en = spl_lang_type_node(sema->type, expected); + if (!en || (en->kind != SPL_LANG_TYPE_STRUCT && en->kind != SPL_LANG_TYPE_UNION)) + break; + + if (n->aggregate_literal.name) { + spl_symbol_t sym; + if (!spl_scope_find(sema->scope, n->aggregate_literal.name, &sym)) { + SPL_ERROR(&n->dbg, "unknown type `%s`", n->aggregate_literal.name); + sema->error_count++; + return 0; + } + spl_def_node_t *def = spl_def_node(sema->type, sym.node); + if (!def || def->lang_id != expected) { + SPL_ERROR(&n->dbg, "aggregate `%s` does not match expected type", + n->aggregate_literal.name); + sema->error_count++; + return 0; + } + } + + spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, expected); + spl_type_node_t *irn = spl_type_node(sema->type, agg_ir); + if (!irn) + return 0; + usize nfields = vec_size(irn->agg_type.variants); + bool *seen = calloc(nfields ? nfields : 1, sizeof(bool)); + + 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; + usize idx = 0; + if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) { + SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name); + sema->error_count++; + continue; + } + if (seen[idx]) { + SPL_ERROR(&item->dbg, "duplicate field `%s`", item->struct_init_item.name); + sema->error_count++; + continue; + } + seen[idx] = true; + spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx); + spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); + if (!ft) + continue; + if (!item->struct_init_item.expr) { + SPL_ERROR(&item->dbg, "field `%s` requires initializer", + item->struct_init_item.name); + sema->error_count++; + continue; + } + sema_check(sema, item->struct_init_item.expr, ft); + } + for (usize i = 0; i < nfields; ++i) { + if (!seen[i]) { + SPL_ERROR(&n->dbg, "missing field `%s`", vec_at(irn->agg_type.variants, i).name); + sema->error_count++; + } + } + free(seen); + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + + case SPL_AST_EXPR_IF: { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, n->if_expr.cond, bt); + if (n->if_expr.then_block) + sema_check(sema, n->if_expr.then_block, expected); + if (n->if_expr.else_branch) + sema_check(sema, n->if_expr.else_branch, expected); + n->resolved_lang_tid = expected; + n->expected_lang_tid = 0; + return expected; + } + + case SPL_AST_EXPR_BLOCK: { + for (usize i = 0; i < vec_size(n->block.stmts); ++i) + sema_infer(sema, vec_at(n->block.stmts, i)); + if (n->block.tail_expr) { + spl_lang_type_id_t t = sema_check(sema, n->block.tail_expr, expected); + if (!t) + return 0; + n->resolved_lang_tid = t; + n->expected_lang_tid = 0; + return t; + } + spl_lang_type_id_t u = spl_lang_make_unit(sema->type); + n->resolved_lang_tid = u; + n->expected_lang_tid = 0; + return u; + } + + default: + break; + } + + /* ============ 类 2:字面量 —— 就地定型 ============ */ + if (sema_is_literal(n)) { + spl_lang_type_id_t from = n->resolved_lang_tid; + if (!from) { + from = sema_infer(sema, ref); + if (!from) + return 0; + } + if (from == expected) + return expected; + spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected, from); + if (!r) { + SPL_ERROR(&n->dbg, "literal cannot coerce to expected type"); + sema->error_count++; + return 0; + } + n->resolved_lang_tid = r; + n->expected_lang_tid = 0; + return r; + } + + /* ============ 类 3:引用性节点 —— 只记 expected ============ */ + { + spl_lang_type_id_t from = sema_infer(sema, ref); + if (!from) + return 0; + if (from == expected) { + n->expected_lang_tid = 0; + return expected; + } + spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected, from); + if (!r) { + SPL_ERROR(&n->dbg, "type mismatch: cannot coerce to expected type"); + sema->error_count++; + return 0; + } + n->expected_lang_tid = expected; /* 只记,不改 natural */ + return expected; + } +} + +static spl_lang_type_id_t sema_infer(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_EXPR_INT_LIT: { + spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1); /* comptime_int */ + n->resolved_lang_tid = t; + return t; + } + case SPL_AST_EXPR_FLOAT_LIT: { + spl_lang_type_id_t t = spl_lang_make_float(sema->type, 0); /* comptime_float */ + n->resolved_lang_tid = t; + return t; + } + case SPL_AST_EXPR_CHAR_LIT: { + spl_lang_type_id_t t = spl_lang_make_int(sema->type, 8, 0); + n->resolved_lang_tid = t; + return t; + } + case SPL_AST_EXPR_STRING_LIT: { + spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); + spl_lang_type_id_t s = spl_lang_make_slice(sema->type, u8); + n->resolved_lang_tid = s; + return s; + } + case SPL_AST_EXPR_BOOL_LIT: { + spl_lang_type_id_t t = spl_lang_make_bool(sema->type); + n->resolved_lang_tid = t; + return t; + } + case SPL_AST_EXPR_NULL_LIT: { + spl_lang_type_id_t nv = spl_lang_make_never(sema->type); + spl_lang_type_id_t p = spl_lang_make_ptr(sema->type, nv); + n->resolved_lang_tid = p; + return p; + } + case SPL_AST_EXPR_UNDEFINED_LIT: { + spl_lang_type_id_t t = spl_lang_make_never(sema->type); + n->resolved_lang_tid = t; + return t; + } + + /* ---------- IDENT:同时写 def_id 和 lang_tid 副本 ---------- */ + 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; + } + n->resolved_lang_tid = def->lang_id; + return def->lang_id; + } + + /* ---------- UNARY ---------- */ + case SPL_AST_EXPR_UNARY: { + spl_lang_type_id_t op = sema_infer(sema, n->unary.operand); + if (op == 0) + return 0; + spl_lang_type_node_t *tn = spl_lang_type_node(sema->type, op); + if (!tn) + return 0; + + switch (n->unary.op) { + case SPL_UNARY_OP_MINUS: + 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; + } + n->resolved_lang_tid = op; + return op; + case SPL_UNARY_OP_BIT_NOT: + if (tn->kind != SPL_LANG_TYPE_INT) { + SPL_ERROR(&n->dbg, "bitwise not requires integer operand"); + sema->error_count++; + return 0; + } + n->resolved_lang_tid = op; + return op; + case SPL_UNARY_OP_NOT: { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, n->unary.operand, bt); + n->resolved_lang_tid = bt; + return bt; + } + case SPL_UNARY_OP_ADDRESS: { + spl_lang_type_id_t p = spl_lang_make_ptr(sema->type, op); + n->resolved_lang_tid = p; + return p; + } + default: + UNREACHABLE(); + } + } + + /* ---------- BINARY ---------- */ + case SPL_AST_EXPR_BINARY: { + spl_binary_op_t op = n->binary.op; + + /* 赋值 / 复合赋值 */ + if (op == SPL_OP_ASSIGN || (op >= SPL_OP_ASSIGN_ADD && op <= SPL_OP_ASSIGN_RSHIFT)) { + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + if (!lt) + return 0; + sema_check(sema, n->binary.right, lt); + n->resolved_lang_tid = lt; + return lt; + } + + /* 逻辑 */ + if (op == SPL_OP_BOOL_OR || op == SPL_OP_BOOL_AND) { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, n->binary.left, bt); + sema_check(sema, n->binary.right, bt); + n->resolved_lang_tid = bt; + return bt; + } + + /* 比较 */ + if (op == SPL_OP_CMP_EQ || op == SPL_OP_CMP_NE || op == SPL_OP_CMP_LT || + op == SPL_OP_CMP_LE || op == SPL_OP_CMP_GT || op == SPL_OP_CMP_GE) { + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + spl_lang_type_id_t rt = sema_infer(sema, n->binary.right); + if (!lt || !rt) + return 0; + spl_lang_type_id_t common = 0; + if (lt == rt) + common = lt; + else + common = spl_lang_type_balance(sema->type, lt, rt); + if (common) { + sema_check(sema, n->binary.left, common); + sema_check(sema, n->binary.right, common); + } + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + n->resolved_lang_tid = bt; + return bt; + } + + /* Range */ + if (op == SPL_OP_RANGE) { + sema_infer(sema, n->binary.left); + sema_infer(sema, n->binary.right); + spl_lang_type_id_t i64 = spl_lang_make_int(sema->type, 64, 1); + spl_lang_type_id_t r = spl_lang_make_range(sema->type, i64); + n->resolved_lang_tid = r; + return r; + } + + /* 移位:结果 = 左类型 */ + if (op == SPL_OP_LSHIFT || op == SPL_OP_RSHIFT) { + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + if (!lt) + return 0; + spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt); + if (!ln || ln->kind != SPL_LANG_TYPE_INT) { + SPL_ERROR(&n->dbg, "shift requires integer operands"); + sema->error_count++; + return 0; + } + sema_infer(sema, n->binary.right); + n->resolved_lang_tid = lt; + return lt; + } + + /* 算术 / 位运算 */ + spl_lang_type_id_t lt = sema_infer(sema, n->binary.left); + spl_lang_type_id_t rt = sema_infer(sema, n->binary.right); + if (!lt || !rt) + return 0; + + spl_lang_type_id_t common = 0; + if (lt == rt) + common = lt; + else + common = spl_lang_type_balance(sema->type, lt, rt); + + /* balance 失败:comptime + 具体时取具体 */ + if (!common) { + 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_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id); + spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id); + if (lir && lir->int_type.bits == 0) + common = rt; + else if (rir && rir->int_type.bits == 0) + common = lt; + } else if (ln && ln->kind == SPL_LANG_TYPE_FLOAT && rn && + rn->kind == SPL_LANG_TYPE_FLOAT) { + spl_type_node_t *lir = spl_type_node(sema->type, ln->ir_type_id); + spl_type_node_t *rir = spl_type_node(sema->type, rn->ir_type_id); + if (lir && lir->float_type.bits == 0) + common = rt; + else if (rir && rir->float_type.bits == 0) + common = lt; + } + } + if (!common) { + SPL_ERROR(&n->dbg, "arithmetic operands type mismatch"); + sema->error_count++; + return 0; + } + sema_check(sema, n->binary.left, common); + sema_check(sema, n->binary.right, common); + n->resolved_lang_tid = common; + return common; + } + + /* ---------- CALL ---------- */ + case SPL_AST_EXPR_CALL: { + spl_ast_node_t *callee = spl_ast_node(sema->ast, n->call.callee); + if (callee && callee->kind == SPL_AST_EXPR_IDENT) { + spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name); + if (in != SPL_INTRIN_NONE) { + spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->call.args); + n->resolved_lang_tid = t; + return t; + } + } + + spl_lang_type_id_t callee_tid = sema_infer(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; + } + + bool has_varargs = false; + usize fixed = vec_size(fn->extra.fn.params); + if (fixed > 0) { + spl_lang_type_id_t last = vec_at(fn->extra.fn.params, fixed - 1); + spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, last); + if (ln && ln->kind == SPL_LANG_TYPE_VARARGS) { + has_varargs = true; + fixed--; + } + } + + usize nargs = vec_size(n->call.args); + if (has_varargs) { + if (nargs < fixed) { + SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed); + sema->error_count++; + } + } else if (nargs != fixed) { + SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)", fixed, nargs); + sema->error_count++; + } + + /* 固定参数:check 到形参类型 */ + for (usize i = 0; i < nargs && i < fixed; ++i) { + spl_lang_type_id_t pt = vec_at(fn->extra.fn.params, i); + sema_check(sema, vec_at(n->call.args, i), pt); + } + /* varargs:默认提升到 isize */ + if (has_varargs) { + spl_lang_type_id_t vt = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); + for (usize i = fixed; i < nargs; ++i) + sema_check(sema, vec_at(n->call.args, i), vt); + } + + spl_lang_type_id_t ret = fn->extra.fn.ret; + n->resolved_lang_tid = ret; + return ret; + } + + /* ---------- FIELD ---------- */ + case SPL_AST_EXPR_FIELD: { + spl_lang_type_id_t obj_tid = sema_infer(sema, n->field.obj); + spl_lang_type_node_t *obj = spl_lang_type_node(sema->type, obj_tid); + if (!obj) + return 0; + + spl_intrin_t in = spl_intrin_lookup_field(obj->kind, n->field.field); + if (in != SPL_INTRIN_NONE) { + spl_lang_type_id_t t = sema_intrin_field(sema, n, in); + n->resolved_lang_tid = t; + return t; + } + + spl_lang_type_id_t agg_lang = obj_tid; + if (obj->kind == SPL_LANG_TYPE_PTR) + agg_lang = obj->extra.elem; + spl_lang_type_node_t *agg = spl_lang_type_node(sema->type, agg_lang); + if (!agg || (agg->kind != SPL_LANG_TYPE_STRUCT && agg->kind != SPL_LANG_TYPE_UNION)) { + SPL_ERROR(&n->dbg, "field access on non-aggregate type"); + sema->error_count++; + return 0; + } + spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); + const spl_type_member_t *m = spl_type_agg_member(sema->type, agg_ir, n->field.field); + if (!m) { + SPL_ERROR(&n->dbg, "no field `%s`", n->field.field); + sema->error_count++; + return 0; + } + spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); + if (!ft) { + SPL_ERROR(&n->dbg, "cannot resolve field type"); + sema->error_count++; + return 0; + } + n->resolved_lang_tid = ft; + return ft; + } + + /* ---------- INDEX ---------- */ + case SPL_AST_EXPR_INDEX: { + spl_lang_type_id_t obj_tid = sema_infer(sema, n->index.obj); + sema_infer(sema, n->index.index); + spl_lang_type_node_t *obj = spl_lang_type_node(sema->type, obj_tid); + if (!obj) + return 0; + spl_lang_type_id_t elem = 0; + switch (obj->kind) { + case SPL_LANG_TYPE_ARRAY: + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + case SPL_LANG_TYPE_PTR: + elem = obj->extra.elem; + break; + case SPL_LANG_TYPE_TUPLE: + if (vec_size(obj->extra.elems) > 0) + elem = vec_at(obj->extra.elems, 0); + break; + default: + SPL_ERROR(&n->dbg, "index base must be array/slice/ptr/range/tuple"); + sema->error_count++; + return 0; + } + n->resolved_lang_tid = elem; + return elem; + } + + /* ---------- SLICE ---------- */ + case SPL_AST_EXPR_SLICE: { + spl_lang_type_id_t obj_tid = sema_infer(sema, n->slice.obj); + if (n->slice.begin) + sema_infer(sema, n->slice.begin); + if (n->slice.end) + sema_infer(sema, n->slice.end); + spl_lang_type_node_t *obj = spl_lang_type_node(sema->type, obj_tid); + if (!obj) + return 0; + spl_lang_type_id_t elem = 0; + if (obj->kind == SPL_LANG_TYPE_ARRAY || obj->kind == SPL_LANG_TYPE_PTR || + obj->kind == SPL_LANG_TYPE_SLICE) { + elem = obj->extra.elem; + } else { + SPL_ERROR(&n->dbg, "slice base must be array/ptr/slice"); + sema->error_count++; + return 0; + } + spl_lang_type_id_t s = spl_lang_make_slice(sema->type, elem); + n->resolved_lang_tid = s; + return s; + } + + /* ---------- CAST ---------- */ + case SPL_AST_EXPR_CAST: { + spl_lang_type_id_t src = sema_infer(sema, n->cast.expr); + spl_lang_type_id_t dst = sema_infer(sema, n->cast.type); + if (!src || !dst) + return 0; + spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src); + if (sn && !(sn->kind == SPL_LANG_TYPE_INT || sn->kind == SPL_LANG_TYPE_FLOAT || + sn->kind == SPL_LANG_TYPE_BOOL || sn->kind == SPL_LANG_TYPE_PTR)) { + SPL_ERROR(&n->dbg, "invalid cast from non-primitive type"); + sema->error_count++; + return 0; + } + n->resolved_lang_tid = dst; + return dst; + } + + /* ---------- TUPLE ---------- */ + case SPL_AST_EXPR_TUPLE: { + spl_lang_type_id_vec_t es; + vec_init(es); + for (usize i = 0; i < vec_size(n->tuple.elems); ++i) + vec_push(es, sema_infer(sema, vec_at(n->tuple.elems, i))); + spl_lang_type_id_t t = + spl_lang_make_tuple(sema->type, vec_unsafe_get_data(es), vec_size(es)); + vec_free(es); + n->resolved_lang_tid = t; + return t; + } + + /* ---------- ARRAY_LIT ---------- */ + case SPL_AST_EXPR_ARRAY_LIT: { + spl_lang_type_id_t elem_t = 0; + if (n->array_literal.elem_type) + elem_t = sema_infer(sema, n->array_literal.elem_type); + + usize nelems = vec_size(n->array_literal.elems); + for (usize i = 0; i < nelems; ++i) { + spl_lang_type_id_t et = sema_infer(sema, vec_at(n->array_literal.elems, i)); + if (!et) + return 0; + if (elem_t == 0) + elem_t = et; + else { + spl_lang_type_id_t c = spl_lang_type_balance(sema->type, elem_t, et); + if (c) + elem_t = c; + } + } + if (elem_t == 0) + elem_t = spl_lang_make_infer(sema->type); + usize len = n->array_literal.is_underscore_len ? nelems + : n->array_literal.has_len ? (usize)n->array_literal.len + : nelems; + spl_lang_type_id_t arr = spl_lang_make_array(sema->type, elem_t, len); + n->resolved_lang_tid = arr; + return arr; + } + + /* ---------- AGGREGATE_LIT ---------- */ + case SPL_AST_EXPR_AGGREGATE_LIT: { + const char *type_name = n->aggregate_literal.name; + if (!type_name) { + spl_lang_type_id_t inf = spl_lang_make_infer(sema->type); + n->resolved_lang_tid = inf; + return inf; + } + 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); + 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 = def->lang_id; + spl_lang_type_node_t *an = spl_lang_type_node(sema->type, agg); + if (!an || (an->kind != SPL_LANG_TYPE_STRUCT && an->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); + spl_type_node_t *irn = spl_type_node(sema->type, agg_ir); + if (irn) { + 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; + usize idx = 0; + if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, + &idx)) { + SPL_ERROR(&item->dbg, "no field `%s`", item->struct_init_item.name); + sema->error_count++; + continue; + } + spl_type_member_t *m = &vec_at(irn->agg_type.variants, idx); + spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); + if (ft && item->struct_init_item.expr) + sema_check(sema, item->struct_init_item.expr, ft); + } + } + n->resolved_lang_tid = agg; + return agg; + } + + /* ---------- COMPTIME_CALL ---------- */ + case SPL_AST_EXPR_COMPTIME_CALL: { + spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); + if (in == SPL_INTRIN_NONE) { + SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name); + sema->error_count++; + return 0; + } + spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args); + n->resolved_lang_tid = t; + return t; + } + + /* ---------- BLOCK ---------- */ + case SPL_AST_EXPR_BLOCK: { + spl_lang_type_id_t last = 0; + for (usize i = 0; i < vec_size(n->block.stmts); ++i) + last = sema_infer(sema, vec_at(n->block.stmts, i)); + if (n->block.tail_expr) + last = sema_infer(sema, n->block.tail_expr); + n->resolved_lang_tid = last; + return last; + } + + /* ---------- IF ---------- */ + case SPL_AST_EXPR_IF: { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, n->if_expr.cond, bt); + + spl_lang_type_id_t then_t = + n->if_expr.then_block ? sema_infer(sema, n->if_expr.then_block) : 0; + spl_lang_type_id_t else_t = + n->if_expr.else_branch ? sema_infer(sema, n->if_expr.else_branch) : 0; + spl_lang_type_id_t result = 0; + if (then_t && else_t) + result = spl_lang_type_balance(sema->type, then_t, else_t); + else + result = then_t ? then_t : else_t; + n->resolved_lang_tid = result; + return result; + } + + /* ---------- IFVAR / WHILE / LOOP / FOR / MATCH ---------- */ + case SPL_AST_EXPR_IFVAR: + sema_infer(sema, n->ifvar_expr.var_decl); + if (n->ifvar_expr.then_block) + sema_infer(sema, n->ifvar_expr.then_block); + if (n->ifvar_expr.else_branch) + sema_infer(sema, n->ifvar_expr.else_branch); + return 0; + case SPL_AST_EXPR_WHILE: { + spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); + sema_check(sema, n->while_expr.cond, bt); + if (n->while_expr.body) + sema_infer(sema, n->while_expr.body); + if (n->while_expr.else_branch) + sema_infer(sema, n->while_expr.else_branch); + return 0; + } + case SPL_AST_EXPR_LOOP: + if (n->loop_expr.body) + sema_infer(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_lang_type_id_t container_tid = sema_infer(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) { + 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; + id_node->resolved_lang_tid = elem_tid; + } + } + } + } + if (n->for_expr.body) + sema_infer(sema, n->for_expr.body); + if (n->for_expr.else_branch) + sema_infer(sema, n->for_expr.else_branch); + sema_pop_scope(sema); + return 0; + } + case SPL_AST_EXPR_MATCH: + sema_infer(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_infer(sema, arm->match_arm.pattern); + sema_infer(sema, arm->match_arm.body); + } + } + return 0; + + /* ---------- FN_TYPE ---------- */ + case SPL_AST_EXPR_FN_TYPE: { + spl_lang_type_id_vec_t ps; + vec_init(ps); + for (usize i = 0; i < vec_size(n->fn_type.params); ++i) + vec_push(ps, sema_infer(sema, vec_at(n->fn_type.params, i))); + spl_lang_type_id_t ret = sema_infer(sema, n->fn_type.ret_type); + spl_lang_type_id_t fn = + spl_lang_make_fn(sema->type, ret, vec_unsafe_get_data(ps), vec_size(ps)); + vec_free(ps); + n->resolved_lang_tid = fn; + return fn; + } + + /* ---------- 类型表达式 ---------- */ + case SPL_AST_TYPE_PATH: { + const char *name = n->type_path.name; + spl_lang_type_id_t b = spl_type_lookup_builtin(sema->type, name); + if (b) { + n->resolved_lang_tid = b; + return b; + } + 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 || !def->lang_id) + return 0; + n->resolved_lang_tid = def->lang_id; + return def->lang_id; + } + case SPL_AST_TYPE_POINTER: { + spl_lang_type_id_t p = sema_infer(sema, n->type_pointer.pointee); + spl_lang_type_id_t r = spl_lang_make_ptr(sema->type, p); + n->resolved_lang_tid = r; + return r; + } + case SPL_AST_TYPE_ARRAY: { + spl_lang_type_id_t e = sema_infer(sema, n->type_array.elem_type); + usize len = n->type_array.has_len ? (usize)n->type_array.len : 0; + spl_lang_type_id_t r = spl_lang_make_array(sema->type, e, len); + n->resolved_lang_tid = r; + return r; + } + case SPL_AST_TYPE_SLICE: { + spl_lang_type_id_t e = sema_infer(sema, n->type_slice.elem_type); + spl_lang_type_id_t r = spl_lang_make_slice(sema->type, e); + n->resolved_lang_tid = r; + return r; + } + case SPL_AST_TYPE_FN: { + spl_lang_type_id_vec_t ps; + vec_init(ps); + for (usize i = 0; i < vec_size(n->type_fn.params); ++i) + vec_push(ps, sema_infer(sema, vec_at(n->type_fn.params, i))); + spl_lang_type_id_t ret = sema_infer(sema, n->type_fn.ret_type); + spl_lang_type_id_t r = + spl_lang_make_fn(sema->type, ret, vec_unsafe_get_data(ps), vec_size(ps)); + vec_free(ps); + n->resolved_lang_tid = r; + return r; + } + case SPL_AST_TYPE_PAREN: { + usize c = vec_size(n->type_paren.types); + if (c == 0) { + spl_lang_type_id_t u = spl_lang_make_unit(sema->type); + n->resolved_lang_tid = u; + return u; + } + if (c == 1) { + spl_lang_type_id_t t = sema_infer(sema, vec_at(n->type_paren.types, 0)); + n->resolved_lang_tid = t; + return t; + } + spl_lang_type_id_vec_t es; + vec_init(es); + for (usize i = 0; i < c; ++i) + vec_push(es, sema_infer(sema, vec_at(n->type_paren.types, i))); + spl_lang_type_id_t t = + spl_lang_make_tuple(sema->type, vec_unsafe_get_data(es), vec_size(es)); + vec_free(es); + n->resolved_lang_tid = t; + return t; + } + case SPL_AST_TYPE_AGGREGATE: + case SPL_AST_TYPE_COMPTIME_CALL: + return 0; + + /* ---------- 顶层声明 ---------- */ + case SPL_AST_CONTAINER_MEMBERS: + for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) + sema_infer(sema, vec_at(n->container_members.declarations, i)); + return 0; + + case SPL_AST_FN_DECL: { + if (n->resolved_def_id == 0) + Panic("fn `%s` not collected", n->fn_decl.name); + + 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_infer(sema, pd->param_decl.type_expr)); + else + vec_push(param_types, spl_lang_make_varargs(sema->type)); + } + spl_lang_type_id_t ret_tid = sema_infer(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)); + 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_lang_type_id_t p_tid = sema_infer(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_lang_type_id_t old_ret = sema->current_fn_ret_tid; + sema->current_fn_ret_tid = ret_tid; + sema_infer(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_lang_type_id_t mtid = sema_infer(sema, mn->member_decl.type_expr); + spl_type_member_t m = {.name = mn->member_decl.name, + .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); + } + } + 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_ir = spl_type_builder_agg( + sema->type, tk, &members, spl_type_builder_int(sema->type, 32, 1), layout); + vec_free(members); + + spl_lang_type_kind_t lk; + switch (tk) { + case SPL_TYPE_STRUCT: + lk = SPL_LANG_TYPE_STRUCT; + break; + case SPL_TYPE_UNION: + lk = SPL_LANG_TYPE_UNION; + break; + case SPL_TYPE_ENUM: + lk = SPL_LANG_TYPE_ENUM; + break; + case SPL_TYPE_SHAPE: + lk = SPL_LANG_TYPE_SHAPE; + break; + default: + lk = SPL_LANG_TYPE_STRUCT; + break; + } + spl_lang_type_node_t ln = {0}; + ln.kind = lk; + ln.ir_type_id = agg_ir; + spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln); + spl_def_resolve(sema->type, n->resolved_def_id, agg_lang); + n->resolved_lang_tid = agg_lang; + + 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_infer(sema, vec_at(te->type_aggregate.members, i)); + } + } else { + spl_lang_type_id_t tid = sema_infer(sema, n->type_decl.type_expr); + spl_def_resolve(sema->type, n->resolved_def_id, tid); + n->resolved_lang_tid = tid; + } + break; + } + + /* ---------- VAR / CONST ---------- */ + 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_lang_type_id_t decl_tid = 0; + if (n->var_const_decl.type) + decl_tid = sema_infer(sema, n->var_const_decl.type); + + if (!n->var_const_decl.init_expr) { + SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name); + sema->error_count++; + return 0; + } + + if (decl_tid) { + sema_check(sema, n->var_const_decl.init_expr, decl_tid); + } else { + decl_tid = sema_infer(sema, n->var_const_decl.init_expr); + if (!decl_tid || sema_is_infer(sema, decl_tid)) { + SPL_ERROR(&n->dbg, "cannot infer type of `%s`", name); + sema->error_count++; + return 0; + } + } + + spl_def_resolve(sema->type, n->resolved_def_id, decl_tid); + n->resolved_lang_tid = decl_tid; + return decl_tid; + } + + /* ---------- MEMBER / PARAM ---------- */ + case SPL_AST_MEMBER_DECL: + if (n->member_decl.type_expr) + return sema_infer(sema, n->member_decl.type_expr); + return 0; + case SPL_AST_PARAM_DECL: + if (n->param_decl.type_expr) + return sema_infer(sema, n->param_decl.type_expr); + return 0; + + /* ---------- 语句 ---------- */ + case SPL_AST_STATEMENT_RET: { + if (n->statement_ret.expr) { + if (sema->current_fn_ret_tid) + sema_check(sema, n->statement_ret.expr, sema->current_fn_ret_tid); + else + sema_infer(sema, n->statement_ret.expr); + } else if (sema->current_fn_ret_tid) { + spl_lang_type_id_t u = spl_lang_make_unit(sema->type); + if (sema->current_fn_ret_tid != u) { + SPL_ERROR(&n->dbg, "function must return a value"); + 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_infer(sema, n->statement_defer.body); + return 0; + case SPL_AST_STATEMENT_COMPTIME: + if (n->statement_comptime.body) + sema_infer(sema, n->statement_comptime.body); + return 0; + case SPL_AST_STATEMENT_DECL: + if (n->statement_decl.decl) + sema_infer(sema, n->statement_decl.decl); + return 0; + case SPL_AST_STATEMENT_EXPR: + if (n->statement_expr.expr) + sema_infer(sema, n->statement_expr.expr); + return 0; + + case SPL_AST_TOP_LEVEL_BLOCK: + if (n->top_level_block.block) + sema_infer(sema, n->top_level_block.block); + return 0; + + default: + return 0; + } + return 0; +} + static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (ref == 0) return 0; @@ -358,7 +1557,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { lang_node.ir_type_id = agg_ir; spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &lang_node); spl_def_resolve(sema->type, n->resolved_def_id, agg_lang); - n->resolved_type_id = agg_lang; + n->resolved_lang_tid = agg_lang; /* 聚合内部函数:方法后续单独处理,这里暂只做函数体的语义解析 */ for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { @@ -370,7 +1569,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } else { 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; + n->resolved_lang_tid = tid; } break; } @@ -412,11 +1611,11 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - init_node->resolved_type_id = coerce_result; + init_node->resolved_lang_tid = coerce_result; decl_tid = coerce_result; spl_def_resolve(sema->type, n->resolved_def_id, decl_tid); - n->resolved_type_id = decl_tid; + n->resolved_lang_tid = decl_tid; return decl_tid; } @@ -436,39 +1635,39 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { case SPL_AST_EXPR_INT_LIT: { spl_lang_type_id_t ct = spl_lang_make_int(sema->type, 0, 1); - n->resolved_type_id = ct; + n->resolved_lang_tid = ct; return ct; } case SPL_AST_EXPR_FLOAT_LIT: { spl_lang_type_id_t ct = spl_lang_make_float(sema->type, 0); - n->resolved_type_id = ct; + n->resolved_lang_tid = ct; return ct; } case SPL_AST_EXPR_CHAR_LIT: { spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); - n->resolved_type_id = u8; + n->resolved_lang_tid = u8; return u8; } case SPL_AST_EXPR_STRING_LIT: { 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; + n->resolved_lang_tid = slice; return slice; } case SPL_AST_EXPR_BOOL_LIT: { spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_type_id = bt; + n->resolved_lang_tid = bt; return bt; } case SPL_AST_EXPR_NULL_LIT: { 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; + n->resolved_lang_tid = ptr; return ptr; } case SPL_AST_EXPR_UNDEFINED_LIT: { spl_lang_type_id_t t = spl_lang_make_never(sema->type); - n->resolved_type_id = t; + n->resolved_lang_tid = t; return t; } case SPL_AST_EXPR_IDENT: { @@ -491,7 +1690,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = def->lang_id; + n->resolved_lang_tid = def->lang_id; return def->lang_id; } @@ -510,7 +1709,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = operand_tid; + n->resolved_lang_tid = operand_tid; return operand_tid; case SPL_UNARY_OP_NOT: if (tn->kind != SPL_LANG_TYPE_BOOL) { @@ -520,7 +1719,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } { spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_type_id = bt; + n->resolved_lang_tid = bt; return bt; } case SPL_UNARY_OP_BIT_NOT: @@ -529,11 +1728,11 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = operand_tid; + n->resolved_lang_tid = operand_tid; return operand_tid; case SPL_UNARY_OP_ADDRESS: { spl_lang_type_id_t ptr_tid = spl_lang_make_ptr(sema->type, operand_tid); - n->resolved_type_id = ptr_tid; + n->resolved_lang_tid = ptr_tid; return ptr_tid; } default: @@ -556,8 +1755,8 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - rhs->resolved_type_id = r; - n->resolved_type_id = lt; + rhs->resolved_lang_tid = r; + n->resolved_lang_tid = lt; return lt; } @@ -584,8 +1783,8 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - rhs->resolved_type_id = r; - n->resolved_type_id = lt; + rhs->resolved_lang_tid = r; + n->resolved_lang_tid = lt; return lt; } @@ -599,7 +1798,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_type_id = bt; + n->resolved_lang_tid = bt; return bt; } @@ -616,13 +1815,13 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { /* 两边都 coerce 到 bal */ if (lt != bal) { spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left); - ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt); + ln->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, lt); } if (rt != bal) { spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right); - rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt); + rn->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, rt); } - n->resolved_type_id = bal; + n->resolved_lang_tid = bal; return bal; } @@ -643,7 +1842,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_type_id = bt; + n->resolved_lang_tid = bt; return bt; } @@ -656,7 +1855,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = lt; + n->resolved_lang_tid = lt; return lt; } @@ -674,20 +1873,20 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } if (lt != bal) { spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left); - ln->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, lt); + ln->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, lt); } if (rt != bal) { spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right); - rn->resolved_type_id = spl_lang_type_coerce_to(sema->type, bal, rt); + rn->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, rt); } - n->resolved_type_id = bal; + n->resolved_lang_tid = bal; return bal; } case SPL_OP_RANGE: { 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; + n->resolved_lang_tid = range; return range; } @@ -702,8 +1901,8 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (callee && callee->kind == SPL_AST_EXPR_IDENT) { spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name); if (in != SPL_INTRIN_NONE) { - spl_lang_type_id_t t = sema_intrin_call(sema, n, in); - n->resolved_type_id = t; + spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->call.args); + n->resolved_lang_tid = t; return t; } } @@ -743,7 +1942,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); sema->error_count++; } else { - arg_node->resolved_type_id = r; + arg_node->resolved_lang_tid = r; } } } @@ -763,14 +1962,14 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); sema->error_count++; } else { - arg_node->resolved_type_id = r; + arg_node->resolved_lang_tid = r; } } } } spl_lang_type_id_t ret_tid = fn->extra.fn.ret; - n->resolved_type_id = ret_tid; + n->resolved_lang_tid = ret_tid; return ret_tid; } @@ -783,7 +1982,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_intrin_t in = spl_intrin_lookup_field(obj_node->kind, n->field.field); if (in != SPL_INTRIN_NONE) { spl_lang_type_id_t t = sema_intrin_field(sema, n, in); - n->resolved_type_id = t; + n->resolved_lang_tid = t; return t; } @@ -821,7 +2020,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = field_lang; + n->resolved_lang_tid = field_lang; return field_lang; } @@ -855,7 +2054,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } (void)idx_tid; - n->resolved_type_id = elem_lang; + n->resolved_lang_tid = elem_lang; return elem_lang; } @@ -881,7 +2080,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } spl_lang_type_id_t slice_tid = spl_lang_make_slice(sema->type, elem_lang); - n->resolved_type_id = slice_tid; + n->resolved_lang_tid = slice_tid; return slice_tid; } @@ -897,7 +2096,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->error_count++; return 0; } - n->resolved_type_id = dst_tid; + n->resolved_lang_tid = dst_tid; return dst_tid; } @@ -910,7 +2109,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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; + n->resolved_lang_tid = tuple; return tuple; } @@ -933,7 +2132,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "array element type mismatch"); sema->error_count++; } else { - elem_node->resolved_type_id = r; + elem_node->resolved_lang_tid = r; } } } @@ -960,7 +2159,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len); - n->resolved_type_id = arr_tid; + n->resolved_lang_tid = arr_tid; return arr_tid; } case SPL_AST_EXPR_AGGREGATE_LIT: { @@ -1064,7 +2263,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&item->dbg, "field `%s` type mismatch", fname); sema->error_count++; } else { - fv->resolved_type_id = r; + fv->resolved_lang_tid = r; } } @@ -1078,12 +2277,21 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { } free(seen); - n->resolved_type_id = agg_lang; + n->resolved_lang_tid = agg_lang; return agg_lang; } - case SPL_AST_EXPR_COMPTIME_CALL: - return 0; + case SPL_AST_EXPR_COMPTIME_CALL: { + spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); + if (in == SPL_INTRIN_NONE) { + SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name); + sema->error_count++; + return 0; + } + spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args); + n->resolved_lang_tid = t; + return t; + } case SPL_AST_EXPR_BLOCK: { for (usize i = 0; i < vec_size(n->block.stmts); ++i) { @@ -1119,20 +2327,20 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_ast_node_t *tn = spl_ast_node(sema->ast, n->if_expr.then_block); spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, then_t); if (r) - tn->resolved_type_id = r; + tn->resolved_lang_tid = r; } if (else_t != result_t) { spl_ast_node_t *en = spl_ast_node(sema->ast, n->if_expr.else_branch); spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, else_t); if (r) - en->resolved_type_id = r; + en->resolved_lang_tid = r; } } } else { result_t = then_t ? then_t : else_t; } - n->resolved_type_id = result_t; + n->resolved_lang_tid = result_t; return result_t; } @@ -1214,7 +2422,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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; + n->resolved_lang_tid = fn_tid; return fn_tid; } @@ -1223,7 +2431,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_lang_type_id_t builtin = spl_type_lookup_builtin(sema->type, name); if (builtin != 0) { - n->resolved_type_id = builtin; + n->resolved_lang_tid = builtin; return builtin; } @@ -1236,14 +2444,14 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_def_node_t *def = spl_def_node(sema->type, sym.node); if (!def || !def->lang_id) return 0; - n->resolved_type_id = def->lang_id; + n->resolved_lang_tid = def->lang_id; return def->lang_id; } case SPL_AST_TYPE_POINTER: { 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; + n->resolved_lang_tid = ptr_tid; return ptr_tid; } @@ -1251,14 +2459,14 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len); - n->resolved_type_id = arr_tid; + n->resolved_lang_tid = arr_tid; return arr_tid; } case SPL_AST_TYPE_SLICE: { 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; + n->resolved_lang_tid = slice_tid; return slice_tid; } @@ -1272,7 +2480,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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; + n->resolved_lang_tid = fn_tid; return fn_tid; } @@ -1280,7 +2488,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { usize count = vec_size(n->type_paren.types); if (count == 0) { spl_lang_type_id_t unit = spl_lang_make_unit(sema->type); - n->resolved_type_id = unit; + n->resolved_lang_tid = unit; return unit; } if (count == 1) { @@ -1295,7 +2503,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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; + n->resolved_lang_tid = tuple; return tuple; } @@ -1317,7 +2525,7 @@ static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { SPL_ERROR(&n->dbg, "return type mismatch"); sema->error_count++; } else { - en->resolved_type_id = r; + en->resolved_lang_tid = r; } } } @@ -1375,13 +2583,9 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) { spl_ast_node_t *mod = spl_ast_node(sema->ast, module_ref); if (!mod || mod->kind != SPL_AST_CONTAINER_MEMBERS) return; - spl_scope_id_t saved = sema->scope->current_scope; - sema_collect(sema, module_ref); - /* 此时 current_scope == 该 module 的 mod_scope */ - sema_parse(sema, module_ref); - + sema_infer(sema, module_ref); /* 原 sema_parse */ sema->scope->current_scope = saved; }