From 2a84b61e3dcf281d89cdbb233735c68f6cf7d8a0 Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Wed, 16 Sep 2026 20:09:24 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E5=A4=A7=E9=87=8F=E9=87=8D=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nob.c | 3 + stage0/spl_vm.c | 6 +- stage1/spl_ast.c | 52 ++- stage1/spl_ast.h | 3 +- stage1/spl_ast2ir.c | 171 ++++---- stage1/spl_ast2ir.h | 3 +- stage1/spl_intrin.h | 2 +- stage1/spl_lang_type.c | 776 +++++++++++++++++++++++++++++++++ stage1/spl_lang_type.h | 153 +++++++ stage1/spl_scope.c | 46 ++ stage1/spl_scope.h | 42 ++ stage1/spl_sema.c | 474 +++++++++++++------- stage1/spl_sema.h | 51 +-- stage1/spl_tok.c | 15 + stage1/spl_tok.h | 2 + stage1/spl_type.c | 949 ++++------------------------------------- stage1/spl_type.h | 150 +------ stage1/splc0.c | 287 +++++++++---- 18 files changed, 1831 insertions(+), 1354 deletions(-) create mode 100644 stage1/spl_lang_type.c create mode 100644 stage1/spl_lang_type.h create mode 100644 stage1/spl_scope.c create mode 100644 stage1/spl_scope.h create mode 100644 stage1/spl_tok.c diff --git a/nob.c b/nob.c index 3103f27..1956e6b 100644 --- a/nob.c +++ b/nob.c @@ -24,11 +24,14 @@ static const char *test_srcs[] = {"stage0/test_spl_vm.c", VM_SRCS}; static const char *splc0_srcs[] = { "stage1/splc0.c", "stage1/spl_diag.c", + "stage1/spl_tok.c", "stage1/spl_lexer.c", "stage1/spl_ast.c", "stage1/spl_dumptree.c", "stage1/spl_type.c", + "stage1/spl_lang_type.c", "stage1/spl_attr.c", + "stage1/spl_scope.c", "stage1/spl_sema.c", "stage1/spl_intrin.c", "stage1/spl_ir.c", diff --git a/stage0/spl_vm.c b/stage0/spl_vm.c index 686197e..6c3a0f5 100644 --- a/stage0/spl_vm.c +++ b/stage0/spl_vm.c @@ -555,8 +555,8 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth) { #endif if (!vm) return; - vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 1024 * 8; - vm->config.max_call_depth = call_depth > 0 ? call_depth : 128; + vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 1024 * 64; + vm->config.max_call_depth = call_depth > 0 ? call_depth : 65536; vec_init(vm->stacks); vec_realloc(vm->stacks, (usize)vm->config.max_stack_depth); @@ -699,7 +699,7 @@ void spl_vm_set_debug(spl_vm_t *vm, int enabled) { static inline int spl_vm_call(spl_vm_t *vm, spl_vm_val_t addr, spl_vm_val_t nargs) { if (vm->cp >= vm->config.max_call_depth) - VM_ERROR("CALLI: call stack overflow"); + VM_ERROR("call depth exceeded"); // spl_vm_stackdump(vm, vm->sp); PUSH(SPL_STACK_CANARY); /* Shift args right by 1 to create gap for canary at fp-1 */ diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index efe2577..e19c510 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -77,13 +77,38 @@ static spl_dbg_node_t tok_to_dbg(const spl_tok_t *t) { return d; } -/* parser 层的 fatal 发射。diag 为 NULL 时静默。 - * 调用者必须紧跟 return / break,因为 diag_fatal 不终止流程。 */ +/* 渲染 token: `lexeme` at line:col。 + 传入 NULL 表示 parser 走到了输入流末尾。 */ +static void tok_desc(const spl_tok_t *t, char *buf, usize cap) { + if (!t) { + snprintf(buf, cap, ""); + return; + } + if (t->type == TOK_EOF) { + snprintf(buf, cap, "EOF"); + return; + } + const char *kind = spl_tok_type_name(t->type); + if (t->type == TOK_ENDLINE) { + snprintf(buf, cap, "ENDLINE at %zu:%zu", t->line, t->col); + return; + } + if (!t->lexeme || t->len == 0) { + snprintf(buf, cap, "%s at %zu:%zu", kind, t->line, t->col); + return; + } + int n = (int)(t->len > 32 ? 32 : t->len); + snprintf(buf, cap, "%s `%.*s` at %s:%zu:%zu", kind, n, t->lexeme, t->fname, t->line, t->col); +} + #define PARSE_FATAL(p, kind, tok, ...) \ do { \ + (p)->failed = 1; \ if ((p)->diag) { \ + char _tb[80]; \ + tok_desc((tok), _tb, sizeof _tb); \ spl_dbg_node_t _pd = tok_to_dbg(tok); \ - spl_diag_fatal((p)->diag, (kind), &_pd, __VA_ARGS__); \ + spl_diag_fatal((p)->diag, (kind), &_pd, __VA_ARGS__ " (got %s)", _tb); \ } \ } while (0) @@ -1058,7 +1083,26 @@ static spl_ast_node_ref_t parse_type_expr(parser_t *p) { return ref; } - return parse_type_base(p); + spl_ast_node_ref_t base = parse_type_base(p); + if (p->failed || !base) + return base; + + while (peek(p) && peek(p)->type == TOK_DOT) { + const spl_tok_t *dot = peek(p); + advance(p); + const spl_tok_t *seg = peek(p); + if (!seg || seg->type != TOK_IDENT) { + PARSE_FATAL(p, SPL_DIAG_KIND_PARSE_EXPECTED, seg ? seg : dot, + "type: expected identifier after '.'"); + return base; + } + advance(p); + spl_ast_node_ref_t sel = new_node(p, SPL_AST_EXPR_FIELD, dot); + node_at(p->ast, sel)->field.obj = base; + SET_STR_FIELD(p->ast, node_at(p->ast, sel)->field.field, seg); + base = sel; + } + return base; } static spl_ast_node_ref_vec_t parse_expr_list(parser_t *p) { diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index 67be385..9ec0cd5 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -483,7 +483,7 @@ struct spl_ast_node { typedef VEC(spl_ast_node_t) spl_ast_node_vec_t; typedef VEC(char *) spl_ast_cstr_ref_vec_t; -typedef struct { +typedef struct spl_ast { spl_tok_vec_t input; spl_ast_node_vec_t node_buckets; spl_ast_cstr_ref_vec_t str_buckets; @@ -491,6 +491,7 @@ typedef struct { spl_diag_t *diag; } spl_ast_t; +typedef VEC(spl_ast_t *) spl_ast_ptr_vec_t; void spl_ast_init(spl_ast_t *ast, const spl_tok_vec_t *tok_vec /*move*/); void spl_ast_drop(spl_ast_t *ast); diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index ade2005..98e5b94 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -48,7 +48,7 @@ static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n); static spl_ir_node_ref_t emit_zero_value(spl_ast2ir_t *a, spl_type_id_t tid) { - spl_type_node_t *tn = spl_type_node(a->sema->type, tid); + spl_type_node_t *tn = spl_type_node(&a->sema->type->ir, tid); if (!tn) return 0; spl_type_node_kind_t tk = tn->kind; @@ -142,12 +142,12 @@ static spl_ir_node_ref_t ast2ir_intrin_cast(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t v = emit_expr(a, vec_at(*args, 0)); if (!v) return 0; - spl_ast_node_t *src = spl_ast_node(a->sema->ast, vec_at(*args, 0)); + spl_ast_node_t *src = spl_ast_node(a->ast, vec_at(*args, 0)); spl_type_id_t ft = node_ir(a, src); spl_type_id_t tt = 0; if (nargs >= 2) { - spl_ast_node_t *targ = spl_ast_node(a->sema->ast, vec_at(*args, 1)); + spl_ast_node_t *targ = spl_ast_node(a->ast, vec_at(*args, 1)); tt = node_ir(a, targ); } else { tt = node_ir(a, n); @@ -161,11 +161,11 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, 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(*args, 0)); + spl_ast_node_t *arg = spl_ast_node(a->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(*args, 0)); + spl_ast_node_t *arg = spl_ast_node(a->ast, vec_at(*args, 0)); return spl_ir_builder_type_alignof(a->ir, node_ir(a, arg)); } case SPL_INTRIN_ASSERT: { @@ -183,7 +183,7 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, const char *fname = n->dbg.fname ? n->dbg.fname : "?"; const char *user_msg = NULL; if (vec_size(*args) == 2) { - spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(*args, 1)); + spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(*args, 1)); if (mn && mn->kind == SPL_AST_EXPR_STRING_LIT && mn->string_lit.data) user_msg = mn->string_lit.data; } @@ -241,7 +241,7 @@ static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, } static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) { - spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); + spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj); spl_lang_type_id_t recv_lang = node_lang(a, obj); spl_lang_type_node_t *recv = spl_lang_type_node(a->sema->type, recv_lang); if (!recv) @@ -252,7 +252,7 @@ static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) { switch (recv->kind) { case SPL_LANG_TYPE_ARRAY: { - spl_type_node_t *arr = spl_type_node(a->sema->type, recv->ir_type_id); + spl_type_node_t *arr = spl_type_node(&a->sema->type->ir, recv->ir_type_id); if (!arr) return 0; return spl_ir_builder_type_const_int(a->ir, usize_ir, arr->array_type.len); @@ -270,7 +270,7 @@ static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n) { } static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return 0; @@ -290,7 +290,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { return emit_expr(a, n->unary.operand); } case SPL_AST_EXPR_FIELD: { - spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); + spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj); if (!obj) return 0; spl_lang_type_id_t obj_lang = node_lang(a, obj); @@ -320,7 +320,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { return 0; usize idx = 0; - if (!spl_type_agg_member_idx(a->sema->type, agg_ir, n->field.field, &idx)) + if (!spl_type_agg_member_idx(&a->sema->type->ir, agg_ir, n->field.field, &idx)) return 0; spl_lang_type_node_t *agg_ln = spl_lang_type_node(a->sema->type, agg_lang); @@ -330,7 +330,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { return spl_ir_builder_mem_field(a->ir, agg_ir, base, idx); } case SPL_AST_EXPR_INDEX: { - spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->index.obj); + spl_ast_node_t *obj = spl_ast_node(a->ast, n->index.obj); if (!obj) return 0; spl_lang_type_id_t obj_lang = node_lang(a, obj); @@ -345,7 +345,7 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { obj_elem = obj_ln->extra.elem; if (obj_kind == SPL_LANG_TYPE_TUPLE) { - spl_ast_node_t *idx_node = spl_ast_node(a->sema->ast, n->index.index); + spl_ast_node_t *idx_node = spl_ast_node(a->ast, n->index.index); if (!idx_node || idx_node->kind != SPL_AST_EXPR_INT_LIT) return 0; usize i = (usize)idx_node->int_lit.bits; @@ -370,7 +370,8 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { spl_ir_node_ref_t slice_val = emit_expr(a, n->index.obj); if (!slice_val) return 0; - spl_type_id_t ptr_ir = spl_type_builder_ptr(a->sema->type, to_ir_type(a, obj_elem)); + spl_type_id_t ptr_ir = + spl_type_builder_ptr(&a->sema->type->ir, to_ir_type(a, obj_elem)); spl_ir_node_ref_t ptr = spl_ir_builder_agg_extract(a->ir, ptr_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX, slice_val); base = ptr; @@ -400,7 +401,7 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_ spl_type_id_t tt, spl_ir_node_ref_t v) { switch (in) { case SPL_INTRIN_INT_CAST: { - spl_type_node_t *fs = spl_type_node(a->sema->type, ft); + spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft); if (fs && 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); @@ -410,8 +411,8 @@ static spl_ir_node_ref_t ast2ir_emit_cast_builtin(spl_ast2ir_t *a, spl_ast_node_ case SPL_INTRIN_BIT_CAST: return spl_ir_builder_cast_bitcast(a->ir, ft, tt, v); case SPL_INTRIN_FLOAT_CAST: { - spl_type_node_t *fs = spl_type_node(a->sema->type, ft); - spl_type_node_t *ts = spl_type_node(a->sema->type, tt); + spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft); + spl_type_node_t *ts = spl_type_node(&a->sema->type->ir, tt); if (fs && ts && 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); @@ -438,14 +439,14 @@ 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_raw(a, n->cast.expr); if (!v) return 0; - spl_ast_node_t *src = spl_ast_node(a->sema->ast, n->cast.expr); - spl_ast_node_t *dst = spl_ast_node(a->sema->ast, n->cast.type); + spl_ast_node_t *src = spl_ast_node(a->ast, n->cast.expr); + spl_ast_node_t *dst = spl_ast_node(a->ast, n->cast.type); spl_type_id_t ft = node_ir(a, src); spl_type_id_t tt = node_ir(a, dst); if (!ft || !tt) return 0; - spl_intrin_t in = spl_intrin_lookup_cast(a->sema->type, ft, tt); + spl_intrin_t in = spl_intrin_lookup_cast(&a->sema->type->ir, ft, tt); if (in == SPL_INTRIN_NONE) { spl_diag_error(a->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, "as: no conversion between the given types"); @@ -459,7 +460,7 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (!val) return 0; - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n || n->expected_lang_tid == 0) return val; @@ -479,14 +480,14 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { } 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); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return 0; switch (n->kind) { case SPL_AST_EXPR_INT_LIT: { spl_type_id_t it = node_ir(a, n); - spl_type_node_t *itn = spl_type_node(a->sema->type, it); + spl_type_node_t *itn = spl_type_node(&a->sema->type->ir, it); if (itn && itn->kind == SPL_TYPE_FLOAT) { double d = (double)(int64_t)n->int_lit.bits; return spl_ir_builder_type_const_float(a->ir, it, d); @@ -501,7 +502,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) usize len = n->string_lit.len; spl_lang_type_id_t u8_lang = spl_lang_make_int(a->sema->type, 8, 0); spl_type_id_t u8_ir = to_ir_type(a, u8_lang); - spl_type_id_t ptr_u8_ir = spl_type_builder_ptr(a->sema->type, u8_ir); + spl_type_id_t ptr_u8_ir = spl_type_builder_ptr(&a->sema->type->ir, u8_ir); spl_lang_type_id_t usize_lang = spl_lang_make_int(a->sema->type, sizeof(void *) * 8, 0); spl_type_id_t usize_ir = to_ir_type(a, usize_lang); spl_lang_type_id_t arr_lang = spl_lang_make_array(a->sema->type, u8_lang, len); @@ -567,7 +568,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) spl_ir_node_ref_t v = emit_expr(a, n->binary.right); if (!ptr || !v) return 0; - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left); spl_type_id_t t = node_ir(a, ln); spl_ir_builder_mem_store(a->ir, t, ptr, v); return v; @@ -576,7 +577,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) spl_ir_node_ref_t ptr = emit_lvalue(a, n->binary.left); if (!ptr) return 0; - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left); spl_type_id_t t = node_ir(a, ln); spl_ir_node_ref_t lv = spl_ir_builder_mem_load(a->ir, t, ptr); spl_ir_node_ref_t rv = emit_expr(a, n->binary.right); @@ -627,14 +628,14 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (!l || !r) return 0; - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *ln = spl_ast_node(a->ast, n->binary.left); spl_lang_type_id_t lt = node_lang(a, ln); spl_lang_type_node_t *lln = spl_lang_type_node(a->sema->type, lt); if (lln && lln->kind == SPL_LANG_TYPE_PTR && (op == SPL_OP_ADD || op == SPL_OP_SUB)) { spl_lang_type_id_t elem_lang = lln->extra.elem; spl_type_id_t elem_ir = to_ir_type(a, elem_lang); - spl_type_id_t rt_ir = node_ir(a, spl_ast_node(a->sema->ast, n->binary.right)); + spl_type_id_t rt_ir = node_ir(a, spl_ast_node(a->ast, n->binary.right)); spl_ir_node_ref_t off = r; if (op == SPL_OP_SUB) @@ -671,7 +672,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) case SPL_OP_CMP_LE: case SPL_OP_CMP_GT: case SPL_OP_CMP_GE: { - spl_ast_node_t *cmln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *cmln = spl_ast_node(a->ast, n->binary.left); spl_type_id_t op_tid = cmln ? node_ir(a, cmln) : 0; switch (op) { case SPL_OP_CMP_EQ: @@ -691,12 +692,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) } } case SPL_OP_BOOL_OR: { - spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left); spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0; return spl_ir_builder_arith_or(a->ir, op_tid, l, r); } case SPL_OP_BOOL_AND: { - spl_ast_node_t *bmln = spl_ast_node(a->sema->ast, n->binary.left); + spl_ast_node_t *bmln = spl_ast_node(a->ast, n->binary.left); spl_type_id_t op_tid = bmln ? node_ir(a, bmln) : 0; return spl_ir_builder_arith_and(a->ir, op_tid, l, r); } @@ -705,7 +706,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) } } case SPL_AST_EXPR_CALL: { - spl_ast_node_t *callee = spl_ast_node(a->sema->ast, n->call.callee); + spl_ast_node_t *callee = spl_ast_node(a->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) @@ -736,7 +737,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) return call; } case SPL_AST_EXPR_FIELD: { - spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->field.obj); + spl_ast_node_t *obj = spl_ast_node(a->ast, n->field.obj); spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); if (obj_ln) { @@ -823,7 +824,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (!t) Panic("aggregate literal has no type after sema"); - spl_type_node_t *tn = spl_type_node(a->sema->type, t); + spl_type_node_t *tn = spl_type_node(&a->sema->type->ir, t); if (!tn) Panic("aggregate type node missing"); @@ -832,13 +833,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (tn_kind == SPL_TYPE_ENUM) { if (vec_size(n->aggregate_literal.fields) != 1) Panic("enum literal must have exactly one variant"); - spl_ast_node_t *item = - spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, 0)); + spl_ast_node_t *item = spl_ast_node(a->ast, vec_at(n->aggregate_literal.fields, 0)); if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) Panic("invalid enum literal"); usize vidx = 0; - if (!spl_type_agg_member_idx(a->sema->type, t, item->struct_init_item.name, &vidx)) + if (!spl_type_agg_member_idx(&a->sema->type->ir, t, item->struct_init_item.name, &vidx)) Panic("enum variant `%s` not found (sema should have caught this)", item->struct_init_item.name); @@ -873,13 +873,12 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) vec_push(fields, 0); for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { - spl_ast_node_t *item = - spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, i)); + spl_ast_node_t *item = spl_ast_node(a->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(a->sema->type, t, item->struct_init_item.name, &idx)) + if (!spl_type_agg_member_idx(&a->sema->type->ir, t, item->struct_init_item.name, &idx)) Panic("aggregate field `%s` not found (sema should have caught this)", item->struct_init_item.name); @@ -936,7 +935,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) case SPL_AST_EXPR_LOOP: return emit_loop_like(a, ref); case SPL_AST_EXPR_SLICE: { - spl_ast_node_t *obj = spl_ast_node(a->sema->ast, n->slice.obj); + spl_ast_node_t *obj = spl_ast_node(a->ast, n->slice.obj); spl_lang_type_id_t obj_lang = node_lang(a, obj); spl_lang_type_node_t *obj_ln = spl_lang_type_node(a->sema->type, obj_lang); if (!obj_ln) @@ -962,7 +961,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) spl_ir_node_ref_t slice_val = emit_expr(a, n->slice.obj); if (!slice_val) return 0; - spl_type_id_t ptr_ir = spl_type_builder_ptr((spl_type_t *)a->sema->type, elem_ir); + spl_type_id_t ptr_ir = spl_type_builder_ptr(&a->sema->type->ir, elem_ir); base = spl_ir_builder_agg_extract(a->ir, obj_ir, ptr_ir, SPL_SLICE_PTR_FIELD_IDX, slice_val); } else { @@ -987,7 +986,7 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) if (n->slice.end) { end_v = emit_expr(a, n->slice.end); } else if (obj_kind == SPL_LANG_TYPE_ARRAY) { - spl_type_node_t *arr = spl_type_node(a->sema->type, obj_ir); + spl_type_node_t *arr = spl_type_node(&a->sema->type->ir, obj_ir); if (!arr) return 0; usize arr_len = arr->array_type.len; @@ -1024,13 +1023,13 @@ 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_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return 0; bool is_ifvar = (n->kind == SPL_AST_EXPR_IFVAR); spl_type_id_t result_t = node_ir(a, n); - spl_type_node_t *rtn = result_t ? spl_type_node(a->sema->type, result_t) : NULL; + spl_type_node_t *rtn = result_t ? spl_type_node(&a->sema->type->ir, result_t) : NULL; bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT; spl_ir_node_ref_t result_slot = 0; @@ -1043,7 +1042,7 @@ static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (is_ifvar) { emit_decl(a, n->ifvar_expr.var_decl); - spl_ast_node_t *vd = spl_ast_node(a->sema->ast, n->ifvar_expr.var_decl); + spl_ast_node_t *vd = spl_ast_node(a->ast, n->ifvar_expr.var_decl); if (!vd || !vd->var_const_decl.init_expr) Panic("ifvar requires initializer"); spl_ir_node_ref_t slot = 0; @@ -1098,13 +1097,13 @@ static spl_ir_node_ref_t emit_if_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { } static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return 0; bool is_while = (n->kind == SPL_AST_EXPR_WHILE); spl_type_id_t result_t = node_ir(a, n); - spl_type_node_t *rtn = result_t ? spl_type_node(a->sema->type, result_t) : NULL; + spl_type_node_t *rtn = result_t ? spl_type_node(&a->sema->type->ir, result_t) : NULL; bool need_result = rtn && rtn->kind != SPL_TYPE_UNIT; spl_ir_node_ref_t result_slot = 0; @@ -1139,7 +1138,7 @@ static spl_ir_node_ref_t emit_loop_like(spl_ast2ir_t *a, spl_ast_node_ref_t ref) spl_ast_node_ref_t label_ref = is_while ? n->while_expr.label : n->loop_expr.label; if (label_ref) { - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, label_ref); + spl_ast_node_t *ln = spl_ast_node(a->ast, label_ref); if (ln && ln->kind == SPL_AST_LABEL) ctx.label = ln->label.name; } @@ -1186,7 +1185,7 @@ static void emit_break_stmt(spl_ast2ir_t *a, spl_ast_node_t *n) { const char *lbl = NULL; if (n->statement_break.label) { - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_break.label); + spl_ast_node_t *ln = spl_ast_node(a->ast, n->statement_break.label); if (ln && ln->kind == SPL_AST_LABEL) lbl = ln->label.name; } @@ -1217,7 +1216,7 @@ static void emit_break_stmt(spl_ast2ir_t *a, spl_ast_node_t *n) { } static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return; @@ -1272,7 +1271,7 @@ static void emit_stmt(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { const char *lbl = NULL; if (n->statement_continue.label) { - spl_ast_node_t *ln = spl_ast_node(a->sema->ast, n->statement_continue.label); + spl_ast_node_t *ln = spl_ast_node(a->ast, n->statement_continue.label); if (ln && ln->kind == SPL_AST_LABEL) lbl = ln->label.name; } @@ -1304,7 +1303,7 @@ 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) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return; @@ -1316,7 +1315,7 @@ static void emit_decl(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (!n->resolved_def_id) return; - spl_ast_node_t *pat = spl_ast_node(a->sema->ast, n->var_const_decl.pattern); + spl_ast_node_t *pat = spl_ast_node(a->ast, n->var_const_decl.pattern); if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) return; @@ -1393,7 +1392,7 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) { for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { spl_ast_node_ref_t pref = vec_at(n->fn_decl.params, i); - spl_ast_node_t *pd = spl_ast_node(a->sema->ast, pref); + spl_ast_node_t *pd = spl_ast_node(a->ast, pref); if (!pd || pd->kind != SPL_AST_PARAM_DECL) continue; if (!pd->resolved_def_id) @@ -1451,13 +1450,13 @@ static void emit_fn_body(spl_ast2ir_t *a, spl_ast_node_t *n) { static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) { for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { - spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i)); + spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(te->type_aggregate.members, i)); if (!mn) continue; if (mn->kind == SPL_AST_FN_DECL) { emit_fn_reserve(a, mn); } else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) { - spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr); + spl_ast_node_t *mt = spl_ast_node(a->ast, mn->member_decl.type_expr); if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE) emit_aggregate_fns_reserve(a, mt); } @@ -1466,13 +1465,13 @@ static void emit_aggregate_fns_reserve(spl_ast2ir_t *a, spl_ast_node_t *te) { static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) { for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { - spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i)); + spl_ast_node_t *mn = spl_ast_node(a->ast, vec_at(te->type_aggregate.members, i)); if (!mn) continue; if (mn->kind == SPL_AST_FN_DECL) { emit_fn_body(a, mn); } else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) { - spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr); + spl_ast_node_t *mt = spl_ast_node(a->ast, mn->member_decl.type_expr); if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE) emit_aggregate_fns_body(a, mt); } @@ -1480,7 +1479,7 @@ static void emit_aggregate_fns_body(spl_ast2ir_t *a, spl_ast_node_t *te) { } static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return; if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) { @@ -1493,7 +1492,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); - spl_ast_node_t *d = spl_ast_node(a->sema->ast, dref); + spl_ast_node_t *d = spl_ast_node(a->ast, dref); if (!d) continue; switch (d->kind) { @@ -1501,7 +1500,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { emit_fn_reserve(a, d); break; case SPL_AST_TYPE_DECL: { - spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr); + spl_ast_node_t *te = spl_ast_node(a->ast, d->type_decl.type_expr); if (te && te->kind == SPL_AST_TYPE_AGGREGATE) emit_aggregate_fns_reserve(a, te); break; @@ -1516,7 +1515,7 @@ static void emit_container_reserve(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { } static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref); + spl_ast_node_t *n = spl_ast_node(a->ast, ref); if (!n) return; if (n->kind == SPL_AST_TOP_LEVEL_BLOCK) { @@ -1529,7 +1528,7 @@ static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); - spl_ast_node_t *d = spl_ast_node(a->sema->ast, dref); + spl_ast_node_t *d = spl_ast_node(a->ast, dref); if (!d) continue; switch (d->kind) { @@ -1537,7 +1536,7 @@ static void emit_container_body(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { emit_fn_body(a, d); break; case SPL_AST_TYPE_DECL: { - spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr); + spl_ast_node_t *te = spl_ast_node(a->ast, d->type_decl.type_expr); if (te && te->kind == SPL_AST_TYPE_AGGREGATE) emit_aggregate_fns_body(a, te); break; @@ -1555,8 +1554,8 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, 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); + spl_type_node_t *fs = spl_type_node(&a->sema->type->ir, ft); + spl_type_node_t *ts = spl_type_node(&a->sema->type->ir, tt); if (!fs || !ts) return v; @@ -1577,8 +1576,6 @@ static spl_ir_node_ref_t emit_implicit_cast(spl_ast2ir_t *a, spl_ast_node_t *n, if (fs->kind == SPL_TYPE_BOOL && ts->kind == SPL_TYPE_INT) return spl_ir_builder_cast_bool2int(a->ir, ft, tt, v); - /* 指针之间:IR 层不区分 pointee,值语义相同,直接透传。 - 覆盖 *never -> *T(null 字面量)和 *T -> *any。 */ if (fs->kind == SPL_TYPE_PTR && ts->kind == SPL_TYPE_PTR) return v; @@ -1598,6 +1595,7 @@ static int spl_int_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema) { ast2ir->sema = sema; ast2ir->ir = ir; + ast2ir->ast = sema->ast; map_init(ast2ir->def2ir_map, spl_int_map_hash, spl_int_map_cmp); vec_init(ast2ir->loop_stack); vec_init(ast2ir->defer_stack); @@ -1615,13 +1613,30 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) { map_free(ast2ir->def2ir_map); } -void spl_ast2ir_run(spl_ast2ir_t *ast2ir) { - spl_ast_t *ast = ast2ir->sema->ast; - if (!ast || !ast->root) - return; - spl_ast_node_t *root = spl_ast_node(ast, ast->root); - if (!root || root->kind != SPL_AST_ROOT) - return; - emit_container_reserve(ast2ir, root->root.members); - emit_container_body(ast2ir, root->root.members); +void spl_ast2ir_run(spl_ast2ir_t *ast2ir, spl_ast_ptr_vec_t ast_vec) { + usize n = vec_size(ast_vec); + + for (usize i = 0; i < n; ++i) { + spl_ast_t *ast = vec_at(ast_vec, i); + if (!ast || !ast->root) + continue; + ast2ir->ast = ast; + spl_ast_node_t *root = spl_ast_node(ast, ast->root); + if (!root || root->kind != SPL_AST_ROOT) + continue; + emit_container_reserve(ast2ir, root->root.members); + } + + for (usize i = 0; i < n; ++i) { + spl_ast_t *ast = vec_at(ast_vec, i); + if (!ast || !ast->root) + continue; + ast2ir->ast = ast; + spl_ast_node_t *root = spl_ast_node(ast, ast->root); + if (!root || root->kind != SPL_AST_ROOT) + continue; + emit_container_body(ast2ir, root->root.members); + } + + vec_free(ast_vec); } diff --git a/stage1/spl_ast2ir.h b/stage1/spl_ast2ir.h index a681cd9..de07780 100644 --- a/stage1/spl_ast2ir.h +++ b/stage1/spl_ast2ir.h @@ -21,6 +21,7 @@ typedef VEC(spl_ast_node_ref_t) spl_defer_stack_t; typedef struct { const spl_sema_t *sema; spl_ir_builder_t *ir; + spl_ast_t *ast; spl_def2ir_map_t def2ir_map; spl_loop_ctx_vec_t loop_stack; spl_defer_stack_t defer_stack; @@ -33,6 +34,6 @@ typedef struct { void spl_ast2ir_init(spl_ast2ir_t *ast2ir, spl_ir_builder_t *ir, const spl_sema_t *sema); void spl_ast2ir_drop(spl_ast2ir_t *ast2ir); -void spl_ast2ir_run(spl_ast2ir_t *ast2ir); +void spl_ast2ir_run(spl_ast2ir_t *ast2ir, spl_ast_ptr_vec_t ast_vec); #endif /* __SPL_AST2IR_H__ */ diff --git a/stage1/spl_intrin.h b/stage1/spl_intrin.h index 0508bab..f1552fa 100644 --- a/stage1/spl_intrin.h +++ b/stage1/spl_intrin.h @@ -2,7 +2,7 @@ #define __SPL_INTRIN_H__ #include "../stage0/include/utils.h" -#include "spl_type.h" +#include "spl_lang_type.h" typedef enum { SPL_INTRIN_NONE = 0, diff --git a/stage1/spl_lang_type.c b/stage1/spl_lang_type.c new file mode 100644 index 0000000..95f7518 --- /dev/null +++ b/stage1/spl_lang_type.c @@ -0,0 +1,776 @@ +#include "spl_lang_type.h" + +static usize spl_lang_type_hash(spl_lang_type_node_t n) { + usize hash = (usize)n.kind * 131 + n.ir_type_id; + switch (n.kind) { + case SPL_LANG_TYPE_PTR: + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + hash += n.extra.elem; + break; + case SPL_LANG_TYPE_TUPLE: + for (usize i = 0; i < vec_size(n.extra.elems); i++) { + hash += vec_at(n.extra.elems, i); + } + break; + case SPL_LANG_TYPE_FN: + hash += n.extra.fn.ret; + for (usize i = 0; i < vec_size(n.extra.fn.params); i++) { + hash += vec_at(n.extra.fn.params, i); + } + break; + case SPL_LANG_TYPE_STRUCT: + case SPL_LANG_TYPE_UNION: + case SPL_LANG_TYPE_ENUM: + case SPL_LANG_TYPE_SHAPE: + for (usize i = 0; i < vec_size(n.methods); i++) { + spl_lang_method_t *m = &vec_at(n.methods, i); + hash += m->def_id * 31; + if (m->name) { + const char *s = m->name; + while (*s) + hash = hash * 31 + (usize)(*s++); + } + } + break; + default: + break; + } + return hash; +} + +static int spl_lang_type_eq(spl_lang_type_node_t n1, spl_lang_type_node_t n2) { + if (n1.kind != n2.kind || n1.ir_type_id != n2.ir_type_id) + return 1; + switch (n1.kind) { + case SPL_LANG_TYPE_PTR: + case SPL_LANG_TYPE_SLICE: + case SPL_LANG_TYPE_RANGE: + return n1.extra.elem != n2.extra.elem; + case SPL_LANG_TYPE_TUPLE: + if (vec_size(n1.extra.elems) != vec_size(n2.extra.elems)) + return 1; + for (usize i = 0; i < vec_size(n1.extra.elems); i++) { + if (vec_at(n1.extra.elems, i) != vec_at(n2.extra.elems, i)) + return 1; + } + return 0; + case SPL_LANG_TYPE_FN: + if (n1.extra.fn.ret != n2.extra.fn.ret) + return 1; + if (vec_size(n1.extra.fn.params) != vec_size(n2.extra.fn.params)) + return 1; + for (usize i = 0; i < vec_size(n1.extra.fn.params); i++) { + if (vec_at(n1.extra.fn.params, i) != vec_at(n2.extra.fn.params, i)) + return 1; + } + return 0; + case SPL_LANG_TYPE_STRUCT: + case SPL_LANG_TYPE_UNION: + case SPL_LANG_TYPE_ENUM: + case SPL_LANG_TYPE_SHAPE: + if (vec_size(n1.methods) != vec_size(n2.methods)) + return 1; + for (usize i = 0; i < vec_size(n1.methods); i++) { + spl_lang_method_t *a = &vec_at(n1.methods, i); + spl_lang_method_t *b = &vec_at(n2.methods, i); + if (a->def_id != b->def_id) + return 1; + if ((a->name == NULL) != (b->name == NULL)) + return 1; + if (a->name && strcmp(a->name, b->name) != 0) + return 1; + } + return 0; + default: + return 0; + } +} + +static usize spl_lang_map_hash(usize k) { return MAP_HASH_INT(k); } +static int spl_lang_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } + +static void spl_lang_node_free_extra(spl_lang_type_node_t *n) { + switch (n->kind) { + case SPL_LANG_TYPE_TUPLE: + vec_free(n->extra.elems); + break; + case SPL_LANG_TYPE_FN: + vec_free(n->extra.fn.params); + break; + case SPL_LANG_TYPE_STRUCT: + case SPL_LANG_TYPE_UNION: + case SPL_LANG_TYPE_ENUM: + case SPL_LANG_TYPE_SHAPE: + vec_free(n->methods); + break; + default: + break; + } +} + +spl_lang_type_id_t spl_lang_node_push(spl_lang_type_t *type, spl_lang_type_node_t *node) { + usize hash = spl_lang_type_hash(*node); + usize idx = (usize)-1; + spl_lang_type_id_t cand = 0; + while (map_get_continue(type->lang_map, hash, &cand, &idx)) { + spl_lang_type_node_t *existing = &vec_at(type->lang_table, cand); + if (spl_lang_type_eq(*existing, *node) == 0) { + spl_lang_node_free_extra(node); + return cand; + } + } + spl_lang_type_id_t id = vec_size(type->lang_table); + vec_push(type->lang_table, *node); + map_put_new(type->lang_map, hash, id); + node->kind = SPL_LANG_TYPE_ERROR; + return id; +} + +void spl_lang_type_init(spl_lang_type_t *type) { + spl_type_init(&type->ir); + + vec_init(type->lang_table); + spl_lang_type_node_t lang_node = {0}; + vec_push(type->lang_table, lang_node); + map_init(type->lang_map, spl_lang_map_hash, spl_lang_map_cmp); + + vec_init(type->def_table); + vec_push(type->def_table, (spl_def_node_t){0}); +} + +void spl_lang_type_drop(spl_lang_type_t *type) { + for (usize i = 0; i < vec_size(type->lang_table); i++) { + spl_lang_type_node_t *n = &vec_at(type->lang_table, i); + spl_lang_node_free_extra(n); + } + map_free(type->lang_map); + vec_free(type->lang_table); + + vec_free(type->def_table); + + spl_type_drop(&type->ir); +} + +spl_lang_type_node_t *spl_lang_type_node(const spl_lang_type_t *type, spl_lang_type_id_t id) { + if (!id || id >= vec_size(type->lang_table)) + return NULL; + return &vec_at(type->lang_table, id); +} + +spl_def_node_t *spl_def_node(const spl_lang_type_t *type, spl_def_id_t id) { + if (!id || id >= vec_size(type->def_table)) + return NULL; + return &vec_at(type->def_table, id); +} + +spl_type_id_t spl_lang_type_get_ir_type(spl_lang_type_t *type, spl_lang_type_id_t lang_id) { + spl_lang_type_node_t *n = spl_lang_type_node(type, lang_id); + return n ? n->ir_type_id : 0; +} + +spl_type_id_t spl_lang_reserve_ir(spl_lang_type_t *type) { + spl_type_node_t empty = {0}; + empty.kind = SPL_TYPE_ERROR; + empty.layout.mode = SPL_TYPE_LAYOUT_AUTO; + vec_push(type->ir.type_table, empty); + return vec_size(type->ir.type_table) - 1; +} + +void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t *node) { + if (!id || id >= vec_size(type->ir.type_table)) + return; + spl_type_node_t *slot = &vec_at(type->ir.type_table, id); + /* slot 原是空 ERROR 节点,无 vec 字段可释放。node 的 vec 字段 move 进 slot。 + 占位 id 不写 type_map,不参与 hash-consing。 */ + *slot = *node; + node->kind = SPL_TYPE_ERROR; +} + +static spl_lang_type_id_t spl_lang_node_simple(spl_lang_type_t *type, + spl_lang_type_kind_t lang_kind, + spl_type_id_t ir_type_id) { + spl_lang_type_node_t node = {0}; + node.kind = lang_kind; + node.ir_type_id = ir_type_id; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_error(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_ERROR); + return spl_lang_node_simple(type, SPL_LANG_TYPE_ERROR, ir); +} + +spl_lang_type_id_t spl_lang_make_infer(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_INFER); + return spl_lang_node_simple(type, SPL_LANG_TYPE_INFER, ir); +} + +spl_lang_type_id_t spl_lang_make_never(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_NEVER); + return spl_lang_node_simple(type, SPL_LANG_TYPE_NEVER, ir); +} + +spl_lang_type_id_t spl_lang_make_any(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_ANY); + return spl_lang_node_simple(type, SPL_LANG_TYPE_ANY, ir); +} + +spl_lang_type_id_t spl_lang_make_unit(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_UNIT); + return spl_lang_node_simple(type, SPL_LANG_TYPE_UNIT, ir); +} + +spl_lang_type_id_t spl_lang_make_bool(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_BOOL); + return spl_lang_node_simple(type, SPL_LANG_TYPE_BOOL, ir); +} + +spl_lang_type_id_t spl_lang_make_int(spl_lang_type_t *type, usize bits, int is_signed) { + spl_type_id_t ir = spl_type_builder_int(&type->ir, bits, is_signed); + return spl_lang_node_simple(type, SPL_LANG_TYPE_INT, ir); +} + +spl_lang_type_id_t spl_lang_make_float(spl_lang_type_t *type, usize bits) { + spl_type_id_t ir = spl_type_builder_float(&type->ir, bits); + return spl_lang_node_simple(type, SPL_LANG_TYPE_FLOAT, ir); +} + +spl_lang_type_id_t spl_lang_make_array(spl_lang_type_t *type, spl_lang_type_id_t elem_lang, + usize len) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + spl_type_id_t ir = spl_type_builder_array(&type->ir, elem_ir, len); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_ARRAY; + node.ir_type_id = ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_ptr(spl_lang_type_t *type, spl_lang_type_id_t pointee_lang) { + spl_type_id_t pointee_ir = spl_lang_type_get_ir_type(type, pointee_lang); + if (!pointee_ir) + return 0; + spl_type_id_t ir = spl_type_builder_ptr(&type->ir, pointee_ir); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_PTR; + node.ir_type_id = ir; + node.extra.elem = pointee_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_slice(spl_lang_type_t *type, spl_lang_type_id_t elem_lang) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + + spl_lang_type_id_t ptr_lang = spl_lang_make_ptr(type, elem_lang); + spl_lang_type_id_t usize_lang = spl_lang_make_int(type, sizeof(void *) * 8, 0); + spl_type_id_t ptr_ir = spl_lang_type_get_ir_type(type, ptr_lang); + spl_type_id_t usize_ir = spl_lang_type_get_ir_type(type, usize_lang); + + spl_type_member_vec_t members; + vec_init(members); + spl_type_member_t m1 = {.name = "ptr", .type_id = ptr_ir}; + spl_type_member_t m2 = {.name = "len", .type_id = usize_ir}; + vec_push(members, m1); + vec_push(members, m2); + + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout); + + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_SLICE; + node.ir_type_id = struct_ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_tuple(spl_lang_type_t *type, const spl_lang_type_id_t *elems, + usize count) { + spl_type_member_vec_t members; + vec_init(members); + for (usize i = 0; i < count; i++) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elems[i]); + if (!elem_ir) { + vec_free(members); + return 0; + } + char name[32]; + snprintf(name, sizeof(name), "%zu", i); + spl_type_member_t m = {.name = strdup(name), .type_id = elem_ir}; + vec_push(members, m); + } + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout); + + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_TUPLE; + node.ir_type_id = struct_ir; + vec_init(node.extra.elems); + for (usize i = 0; i < count; i++) { + vec_push(node.extra.elems, elems[i]); + } + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_range(spl_lang_type_t *type, spl_lang_type_id_t elem_lang) { + spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); + if (!elem_ir) + return 0; + + spl_type_member_vec_t members; + vec_init(members); + spl_type_member_t m1 = {.name = "start", .type_id = elem_ir}; + spl_type_member_t m2 = {.name = "end", .type_id = elem_ir}; + vec_push(members, m1); + vec_push(members, m2); + + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t struct_ir = spl_type_builder_agg(&type->ir, SPL_TYPE_STRUCT, &members, 0, layout); + + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_RANGE; + node.ir_type_id = struct_ir; + node.extra.elem = elem_lang; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_fn(spl_lang_type_t *type, spl_lang_type_id_t ret_lang, + const spl_lang_type_id_t *params_lang, usize nparams) { + spl_type_id_t ret_ir = spl_lang_type_get_ir_type(type, ret_lang); + if (!ret_ir) + return 0; + spl_type_id_vec_t param_irs; + vec_init(param_irs); + for (usize i = 0; i < nparams; i++) { + spl_type_id_t pir = spl_lang_type_get_ir_type(type, params_lang[i]); + if (!pir) { + vec_free(param_irs); + return 0; + } + vec_push(param_irs, pir); + } + spl_type_id_t fn_ir = + spl_type_builder_fn(&type->ir, ret_ir, param_irs.data, vec_size(param_irs)); + vec_free(param_irs); + + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_FN; + node.ir_type_id = fn_ir; + node.extra.fn.ret = ret_lang; + vec_init(node.extra.fn.params); + for (usize i = 0; i < nparams; i++) { + vec_push(node.extra.fn.params, params_lang[i]); + } + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_aggregate(spl_lang_type_t *type, spl_lang_type_kind_t kind, + const char *name, const spl_lang_type_id_t *members_lang, + usize nmembers) { + spl_type_node_kind_t tk; + switch (kind) { + case SPL_LANG_TYPE_STRUCT: + tk = SPL_TYPE_STRUCT; + break; + case SPL_LANG_TYPE_UNION: + tk = SPL_TYPE_UNION; + break; + case SPL_LANG_TYPE_ENUM: + tk = SPL_TYPE_ENUM; + break; + case SPL_LANG_TYPE_SHAPE: + tk = SPL_TYPE_SHAPE; + break; + default: + return 0; + } + + spl_type_member_vec_t members; + vec_init(members); + for (usize i = 0; i < nmembers; i++) { + spl_type_id_t member_ir = spl_lang_type_get_ir_type(type, members_lang[i]); + if (!member_ir) { + vec_free(members); + return 0; + } + char field_name[32]; + snprintf(field_name, sizeof(field_name), "%zu", i); + spl_type_member_t m = {.name = strdup(field_name), .type_id = member_ir}; + vec_push(members, m); + } + spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; + spl_type_id_t agg_ir = spl_type_builder_agg(&type->ir, tk, &members, 0, layout); + + spl_lang_type_node_t node = {0}; + node.kind = kind; + node.ir_type_id = agg_ir; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_lang_make_varargs(spl_lang_type_t *type) { + spl_type_id_t ir = spl_type_builder_simple(&type->ir, SPL_TYPE_UNIT); + spl_lang_type_node_t node = {0}; + node.kind = SPL_LANG_TYPE_VARARGS; + node.ir_type_id = ir; + return spl_lang_node_push(type, &node); +} + +spl_lang_type_id_t spl_type_lookup_builtin(spl_lang_type_t *type, const char *name) { + if (!name || !*name) + return 0; + if (strcmp(name, "bool") == 0) + return spl_lang_make_bool(type); + if (strcmp(name, "void") == 0) + return spl_lang_make_unit(type); + if (strcmp(name, "isize") == 0) + return spl_lang_make_int(type, sizeof(void *) * 8, 1); + if (strcmp(name, "usize") == 0) + return spl_lang_make_int(type, sizeof(void *) * 8, 0); + if (strcmp(name, "any") == 0) + return spl_lang_make_any(type); + char prefix = name[0]; + if (prefix == 'i' || prefix == 'u' || prefix == 'f') { + const char *rest = name + 1; + char *end; + long bits = strtol(rest, &end, 10); + if (end != rest && *end == '\0' && bits > 0) { + if (prefix == 'i') + return spl_lang_make_int(type, (usize)bits, 1); + if (prefix == 'u') + return spl_lang_make_int(type, (usize)bits, 0); + if (prefix == 'f') + return spl_lang_make_float(type, (usize)bits); + } + } + return 0; +} + +bool spl_lang_type_is_subtype(const spl_lang_type_t *type, spl_lang_type_id_t sub, + spl_lang_type_id_t super) { + if (sub == 0 || super == 0) + return false; + if (sub == super) + return true; + + spl_lang_type_node_t *nsub = spl_lang_type_node(type, sub); + spl_lang_type_node_t *nsuper = spl_lang_type_node(type, super); + if (!nsub || !nsuper) + return false; + + if (nsub->kind == SPL_LANG_TYPE_NEVER) + return true; + if (nsuper->kind == SPL_LANG_TYPE_ANY) + return true; + + if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) { + spl_type_node_t *ir_sub = spl_type_node(&type->ir, nsub->ir_type_id); + if (!ir_sub) + return false; + return ir_sub->int_type.bits == 0; + } + + if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) { + spl_type_node_t *ir_sub = spl_type_node(&type->ir, nsub->ir_type_id); + if (!ir_sub) + return false; + return ir_sub->float_type.bits == 0; + } + + if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) { + if (nsub->extra.elem == nsuper->extra.elem) + return true; + spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem); + spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem); + if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER) + return true; + if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY) + return true; + return false; + } + + return false; +} + +spl_lang_type_id_t spl_lang_type_join(const spl_lang_type_t *type, spl_lang_type_id_t a, + spl_lang_type_id_t b) { + if (a == 0 || b == 0) + return 0; + if (a == b) + return a; + + spl_lang_type_node_t *na = spl_lang_type_node(type, a); + spl_lang_type_node_t *nb = spl_lang_type_node(type, b); + if (!na || !nb) + return 0; + + if (na->kind == SPL_LANG_TYPE_NEVER) + return b; + if (nb->kind == SPL_LANG_TYPE_NEVER) + return a; + if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY) + return spl_lang_make_any((spl_lang_type_t *)type); + + bool a_int = na->kind == SPL_LANG_TYPE_INT; + bool b_int = nb->kind == SPL_LANG_TYPE_INT; + bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT; + bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT; + + if (a_int && b_int) { + spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id); + spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id); + if (!ira || !irb) + return 0; + bool a_ct = ira->int_type.bits == 0; + bool b_ct = irb->int_type.bits == 0; + if (a_ct && b_ct) + return a; + if (a_ct) + return b; + if (b_ct) + return a; + return 0; + } + + if (a_flt && b_flt) { + spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id); + spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id); + if (!ira || !irb) + return 0; + bool a_ct = ira->float_type.bits == 0; + bool b_ct = irb->float_type.bits == 0; + if (a_ct && b_ct) + return a; + if (a_ct) + return b; + if (b_ct) + return a; + return 0; + } + + if (a_int && b_flt) { + spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id); + spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id); + if (ira && irb && ira->int_type.bits == 0 && irb->float_type.bits == 0) + return spl_lang_make_float((spl_lang_type_t *)type, 0); + return 0; + } + if (a_flt && b_int) { + spl_type_node_t *ira = spl_type_node(&type->ir, na->ir_type_id); + spl_type_node_t *irb = spl_type_node(&type->ir, nb->ir_type_id); + if (ira && irb && ira->float_type.bits == 0 && irb->int_type.bits == 0) + return spl_lang_make_float((spl_lang_type_t *)type, 0); + return 0; + } + + if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) { + if (na->extra.elem == nb->extra.elem) + return a; + + spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem); + spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem); + + if (ea && ea->kind == SPL_LANG_TYPE_NEVER) + return b; + if (eb && eb->kind == SPL_LANG_TYPE_NEVER) + return a; + if (ea && ea->kind == SPL_LANG_TYPE_ANY) + return a; + if (eb && eb->kind == SPL_LANG_TYPE_ANY) + return b; + + return 0; + } + + return 0; +} + +bool spl_lang_mpa_int_fits(const spl_lang_type_t *type, spl_lang_type_id_t target, + spl_mpa_int_t v) { + spl_lang_type_node_t *nt = spl_lang_type_node(type, target); + if (!nt || nt->kind != SPL_LANG_TYPE_INT) + return false; + spl_type_node_t *ir = spl_type_node(&type->ir, nt->ir_type_id); + if (!ir) + return false; + uint32_t bits = (uint32_t)ir->int_type.bits; + if (bits == 0) + return true; + bool target_signed = ir->int_type.is_signed != 0; + uint64_t uval = v.bits; + + if (target_signed) { + if (bits >= 64) + return true; + uint64_t hi = ((uint64_t)1 << (bits - 1)) - 1; + return uval <= hi; + } + if (bits >= 64) + return true; + uint64_t hi = ((uint64_t)1 << bits) - 1; + return uval <= hi; +} + +spl_def_id_t spl_def_alloc(spl_lang_type_t *type, spl_def_node_kind_t kind, const char *name, + spl_dbg_node_t dbg, struct spl_ast *owner_ast, usize ast_node_ref) { + spl_def_node_t n = {0}; + n.kind = kind; + n.name = name; + n.dbg_node = dbg; + n.lang_id = 0; + n.owner_ast = owner_ast; + n.ast_node_ref = ast_node_ref; + n.state = SPL_DECL_UNRESOLVED; + n.owner_def = 0; + vec_push(type->def_table, n); + return vec_size(type->def_table) - 1; +} + +void spl_def_resolve(spl_lang_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id) { + spl_def_node_t *d = spl_def_node(type, id); + if (d) + d->lang_id = lang_id; +} + +spl_lang_type_id_t spl_def_get_lang_id(spl_lang_type_t *type, spl_def_id_t def_id) { + spl_def_node_t *d = spl_def_node(type, def_id); + return d ? d->lang_id : 0; +} + +spl_type_id_t spl_def_get_type_id(spl_lang_type_t *type, spl_def_id_t def_id) { + spl_lang_type_id_t lang = spl_def_get_lang_id(type, def_id); + return lang ? spl_lang_type_get_ir_type(type, lang) : 0; +} + +void spl_lang_type_dump(spl_lang_type_t *type, spl_lang_type_id_t id) { + spl_lang_type_node_t *n = spl_lang_type_node(type, id); + if (!n) { + printf("none"); + return; + } + switch (n->kind) { + case SPL_LANG_TYPE_ERROR: + printf("error"); + break; + case SPL_LANG_TYPE_INFER: + printf("infer"); + break; + case SPL_LANG_TYPE_NEVER: + printf("never"); + break; + case SPL_LANG_TYPE_ANY: + printf("any"); + break; + case SPL_LANG_TYPE_UNIT: + printf("unit"); + break; + case SPL_LANG_TYPE_BOOL: + printf("bool"); + break; + case SPL_LANG_TYPE_VARARGS: + printf("..."); + break; + case SPL_LANG_TYPE_INT: { + spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id); + if (tn && tn->int_type.bits == 0) + printf("comptime_int"); + else + spl_type_pure_dump(&type->ir, n->ir_type_id); + break; + } + case SPL_LANG_TYPE_FLOAT: { + spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id); + if (tn && tn->float_type.bits == 0) + printf("comptime_float"); + else + spl_type_pure_dump(&type->ir, n->ir_type_id); + break; + } + case SPL_LANG_TYPE_PTR: + printf("*"); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_ARRAY: { + spl_type_node_t *tn = spl_type_node(&type->ir, n->ir_type_id); + printf("[%zu]", tn->array_type.len); + spl_type_pure_dump(&type->ir, n->ir_type_id); + } break; + case SPL_LANG_TYPE_SLICE: + printf("[]"); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_TUPLE: + printf("("); + for (usize i = 0; i < vec_size(n->extra.elems); i++) { + if (i) + printf(","); + spl_lang_type_dump(type, vec_at(n->extra.elems, i)); + } + printf(")"); + break; + case SPL_LANG_TYPE_RANGE: + spl_lang_type_dump(type, n->extra.elem); + printf(".."); + spl_lang_type_dump(type, n->extra.elem); + break; + case SPL_LANG_TYPE_FN: + printf("fn("); + for (usize i = 0; i < vec_size(n->extra.fn.params); i++) { + if (i) + printf(","); + spl_lang_type_dump(type, vec_at(n->extra.fn.params, i)); + } + printf(")"); + spl_lang_type_dump(type, n->extra.fn.ret); + break; + case SPL_LANG_TYPE_STRUCT: + case SPL_LANG_TYPE_UNION: + case SPL_LANG_TYPE_ENUM: + case SPL_LANG_TYPE_SHAPE: + spl_type_pure_dump(&type->ir, n->ir_type_id); + break; + } +} + +void spl_type_def_dump(spl_lang_type_t *type, spl_def_id_t id) { + spl_def_node_t *node = spl_def_node(type, id); + if (!node) { + printf("none"); + return; + } + const char *def_kind_name = "unknown"; + switch (node->kind) { + case SPL_DEF_ERROR: + def_kind_name = "error"; + break; + case SPL_DEF_SCALAR: + def_kind_name = "scalar"; + break; + case SPL_DEF_MEMBER: + def_kind_name = "member"; + break; + case SPL_DEF_VAR: + def_kind_name = "var"; + break; + case SPL_DEF_FN: + def_kind_name = "fn"; + break; + case SPL_DEF_AGG: + def_kind_name = "agg"; + break; + case SPL_DEF_BUILTIN: + def_kind_name = "builtin"; + break; + case SPL_DEF_DISTINCT: + def_kind_name = "distinct"; + break; + case SPL_DEF_ALIAS: + def_kind_name = "alias"; + break; + } + printf("kind=%s lang_id=%zu name=%s", def_kind_name, node->lang_id, + node->name ? node->name : "?"); +} diff --git a/stage1/spl_lang_type.h b/stage1/spl_lang_type.h new file mode 100644 index 0000000..f96f4c5 --- /dev/null +++ b/stage1/spl_lang_type.h @@ -0,0 +1,153 @@ +#ifndef __SPL_LANG_TYPE_H__ +#define __SPL_LANG_TYPE_H__ + +#include "../stage0/include/utils.h" +#include "spl_dbg.h" +#include "spl_mpa.h" +#include "spl_type.h" + +typedef usize spl_lang_type_id_t; +typedef VEC(spl_lang_type_id_t) spl_lang_type_id_vec_t; +typedef usize spl_def_id_t; +typedef VEC(spl_def_id_t) spl_def_id_vec_t; + +typedef enum { + SPL_LANG_TYPE_ERROR, + SPL_LANG_TYPE_INFER, + SPL_LANG_TYPE_NEVER, + SPL_LANG_TYPE_ANY, + SPL_LANG_TYPE_UNIT, + SPL_LANG_TYPE_BOOL, + SPL_LANG_TYPE_INT, + SPL_LANG_TYPE_FLOAT, + SPL_LANG_TYPE_PTR, + SPL_LANG_TYPE_ARRAY, + SPL_LANG_TYPE_SLICE, + SPL_LANG_TYPE_TUPLE, + SPL_LANG_TYPE_RANGE, + SPL_LANG_TYPE_FN, + SPL_LANG_TYPE_STRUCT, + SPL_LANG_TYPE_UNION, + SPL_LANG_TYPE_ENUM, + SPL_LANG_TYPE_SHAPE, + SPL_LANG_TYPE_VARARGS, +} spl_lang_type_kind_t; + +typedef struct { + const char *name; + spl_def_id_t def_id; +} spl_lang_method_t; +typedef VEC(spl_lang_method_t) spl_lang_method_vec_t; + +typedef struct { + spl_lang_type_kind_t kind; + spl_type_id_t ir_type_id; + spl_lang_method_vec_t methods; + union { + spl_lang_type_id_t elem; + spl_lang_type_id_vec_t elems; + struct { + spl_lang_type_id_vec_t params; + spl_lang_type_id_t ret; + } fn; + } extra; +} spl_lang_type_node_t; +typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t; +typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t; + +typedef enum { + SPL_DEF_ERROR, + SPL_DEF_SCALAR, + SPL_DEF_MEMBER, + SPL_DEF_VAR, + SPL_DEF_FN, + SPL_DEF_AGG, + SPL_DEF_DISTINCT, + SPL_DEF_ALIAS, + SPL_DEF_BUILTIN, +} spl_def_node_kind_t; + +typedef enum { + SPL_DECL_UNRESOLVED, + SPL_DECL_RESOLVING, + SPL_DECL_RESOLVED, + SPL_DECL_ERROR, +} spl_decl_state_t; + +struct spl_ast; + +typedef struct { + spl_def_node_kind_t kind; + const char *name; + spl_dbg_node_t dbg_node; + spl_lang_type_id_t lang_id; + struct spl_ast *owner_ast; + usize ast_node_ref; + spl_decl_state_t state; + spl_def_id_t owner_def; +} spl_def_node_t; +typedef VEC(spl_def_node_t) spl_def_node_vec_t; + +typedef struct { + spl_type_t ir; + spl_lang_type_vec_t lang_table; + spl_lang_type_map_t lang_map; + spl_def_node_vec_t def_table; +} spl_lang_type_t; + +void spl_lang_type_init(spl_lang_type_t *type); +void spl_lang_type_drop(spl_lang_type_t *type); + +spl_lang_type_node_t *spl_lang_type_node(const spl_lang_type_t *type, spl_lang_type_id_t id); +spl_lang_type_id_t spl_lang_node_push(spl_lang_type_t *type, spl_lang_type_node_t *node); + +spl_type_id_t spl_lang_type_get_ir_type(spl_lang_type_t *type, spl_lang_type_id_t lang_id); + +/* 前向引用支持:reserve 一个 type_table 空槽位(kind=ERROR)作为身份锚点, + 让 *Node / []Node 这类成员能拿到稳定 pointee;成员解析完后再调 define + 把真实内容填进去。占位槽位**不写 type_map**,不参与 hash-consing—— + 后续相同形状的类型走 spl_type_node_push 会生成独立 id,语义等价。 */ +spl_type_id_t spl_lang_reserve_ir(spl_lang_type_t *type); +void spl_lang_define_ir(spl_lang_type_t *type, spl_type_id_t id, spl_type_node_t *node); + +spl_lang_type_id_t spl_lang_make_error(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_infer(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_never(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_any(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_unit(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_bool(spl_lang_type_t *type); +spl_lang_type_id_t spl_lang_make_int(spl_lang_type_t *type, usize bits, int is_signed); +spl_lang_type_id_t spl_lang_make_float(spl_lang_type_t *type, usize bits); +spl_lang_type_id_t spl_lang_make_ptr(spl_lang_type_t *type, spl_lang_type_id_t pointee); +spl_lang_type_id_t spl_lang_make_array(spl_lang_type_t *type, spl_lang_type_id_t elem, usize len); +spl_lang_type_id_t spl_lang_make_slice(spl_lang_type_t *type, spl_lang_type_id_t elem); +spl_lang_type_id_t spl_lang_make_tuple(spl_lang_type_t *type, const spl_lang_type_id_t *elems, + usize count); +spl_lang_type_id_t spl_lang_make_range(spl_lang_type_t *type, spl_lang_type_id_t elem); +spl_lang_type_id_t spl_lang_make_fn(spl_lang_type_t *type, spl_lang_type_id_t ret, + const spl_lang_type_id_t *params, usize nparams); +spl_lang_type_id_t spl_lang_make_aggregate(spl_lang_type_t *type, spl_lang_type_kind_t kind, + const char *name, const spl_lang_type_id_t *members, + usize nmembers); +spl_lang_type_id_t spl_lang_make_varargs(spl_lang_type_t *type); + +spl_lang_type_id_t spl_type_lookup_builtin(spl_lang_type_t *type, const char *name); + +bool spl_lang_type_is_subtype(const spl_lang_type_t *type, spl_lang_type_id_t sub, + spl_lang_type_id_t super); +spl_lang_type_id_t spl_lang_type_join(const spl_lang_type_t *type, spl_lang_type_id_t a, + spl_lang_type_id_t b); + +bool spl_lang_mpa_int_fits(const spl_lang_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v); + +spl_def_id_t spl_def_alloc(spl_lang_type_t *type, spl_def_node_kind_t kind, const char *name, + spl_dbg_node_t dbg, struct spl_ast *owner_ast, usize ast_node_ref); +void spl_def_resolve(spl_lang_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id); +spl_def_node_t *spl_def_node(const spl_lang_type_t *type, spl_def_id_t id); +spl_lang_type_id_t spl_def_get_lang_id(spl_lang_type_t *type, spl_def_id_t def_id); +spl_type_id_t spl_def_get_type_id(spl_lang_type_t *type, spl_def_id_t def_id); + +void spl_lang_type_dump(spl_lang_type_t *type, spl_lang_type_id_t id); +void spl_type_def_dump(spl_lang_type_t *type, spl_def_id_t id); + +#endif /* __SPL_LANG_TYPE_H__ */ diff --git a/stage1/spl_scope.c b/stage1/spl_scope.c new file mode 100644 index 0000000..e48204e --- /dev/null +++ b/stage1/spl_scope.c @@ -0,0 +1,46 @@ +#include "spl_scope.h" + +void spl_scope_init(spl_scope_t *scope) { + vec_init(scope->scopes); + vec_push(scope->scopes, (spl_scope_node_t){0}); + scope->current_scope = 0; + scope->root_scope = 0; +} + +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 = {0}; + n.parent = scope->current_scope; + map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR); + vec_push(scope->scopes, n); + return vec_size(scope->scopes) - 1; +} + +bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) { + Assert(id != 0 && id < vec_size(scope->scopes)); + spl_scope_node_t *node = &vec_at(scope->scopes, id); + spl_symbol_t old = {0}; + if (map_get(node->symbols, symbol.name, &old)) + return false; + map_put(node->symbols, symbol.name, symbol); + return true; +} + +bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { + 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)) + return true; + } + return false; +} \ No newline at end of file diff --git a/stage1/spl_scope.h b/stage1/spl_scope.h new file mode 100644 index 0000000..a626331 --- /dev/null +++ b/stage1/spl_scope.h @@ -0,0 +1,42 @@ +#ifndef __SPL_SCOPE_H__ +#define __SPL_SCOPE_H__ + +#include "spl_lang_type.h" + +typedef usize spl_scope_id_t; + +typedef enum { + SPL_SYMBOL_KIND_ERROR, + SPL_SYMBOL_KIND_VAR, + SPL_SYMBOL_KIND_MEMBER, + SPL_SYMBOL_KIND_FN, + SPL_SYMBOL_KIND_TYPE, +} spl_symbol_kind_t; + +typedef struct { + const char *name; + spl_symbol_kind_t kind; + spl_def_id_t node; +} spl_symbol_t; + +typedef VEC(const char *) spl_symbol_path_t; + +typedef struct { + spl_scope_id_t parent; + MAP(const char *, spl_symbol_t) symbols; +} spl_scope_node_t; +typedef VEC(spl_scope_node_t) spl_scope_node_vec_t; + +typedef struct { + spl_scope_node_vec_t scopes; + spl_scope_id_t root_scope; + spl_scope_id_t current_scope; +} spl_scope_t; + +void spl_scope_init(spl_scope_t *scope); +void spl_scope_drop(spl_scope_t *scope); +spl_scope_id_t spl_scope_alloc(spl_scope_t *scope); +bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol); +bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out); + +#endif /* __SPL_SCOPE_H__ */ diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index c6a546a..2de8a3a 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -1,52 +1,8 @@ #include "spl_sema.h" #include "spl_intrin.h" +#include "spl_lang_type.h" #include "spl_type.h" -void spl_scope_init(spl_scope_t *scope) { - vec_init(scope->scopes); - vec_push(scope->scopes, (spl_scope_node_t){0}); - scope->current_scope = 0; - scope->root_scope = 0; -} - -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 = {0}; - n.parent = scope->current_scope; - map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR); - vec_push(scope->scopes, n); - return vec_size(scope->scopes) - 1; -} - -bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol) { - Assert(id != 0 && id < vec_size(scope->scopes)); - spl_scope_node_t *node = &vec_at(scope->scopes, id); - spl_symbol_t old = {0}; - if (map_get(node->symbols, symbol.name, &old)) - return false; - map_put(node->symbols, symbol.name, symbol); - return true; -} - -bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { - 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)) - return true; - } - return false; -} - static spl_ast_node_ref_vec_t *node_attr_list(spl_ast_node_t *n) { switch (n->kind) { case SPL_AST_FN_DECL: @@ -168,7 +124,7 @@ static void sema_type_to_str(spl_sema_t *sema, spl_lang_type_id_t tid, char *buf snprintf(buf, cap, "", tid); return; } - spl_type_node_t *ir = spl_type_node(sema->type, n->ir_type_id); + spl_type_node_t *ir = spl_type_node(&sema->type->ir, n->ir_type_id); switch (n->kind) { case SPL_LANG_TYPE_INT: if (ir && ir->int_type.bits == 0) @@ -285,37 +241,10 @@ static spl_lang_type_id_t sema_infer_fn_signature(spl_sema_t *sema, spl_ast_node return fn_tid; } +/* 构建聚合类型:reserve IR 槽位作为身份锚点,让 *Node / []Node 自引用能拿到 + 稳定 pointee;遍历成员后再 define 填内容。 */ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t *te, spl_def_id_t owner_def_id) { - spl_type_member_vec_t members; - vec_init(members); - spl_lang_method_vec_t methods; - vec_init(methods); - - for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { - spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i); - spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); - if (!mn) - continue; - - if (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 = mref}; - vec_push(members, m); - } else if (mn->kind == SPL_AST_FN_DECL) { - spl_def_id_t fn_def = - spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, mref); - mn->resolved_def_id = fn_def; - spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def); - if (fn_d) - fn_d->owner_def = owner_def_id; - spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def}; - vec_push(methods, meth); - } - } - spl_type_node_kind_t tk; if (strcmp(te->type_aggregate.kind_name, "struct") == 0) tk = SPL_TYPE_STRUCT; @@ -326,11 +255,6 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t 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: @@ -349,11 +273,229 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t lk = SPL_LANG_TYPE_STRUCT; break; } + + spl_type_id_t agg_ir = spl_lang_reserve_ir(sema->type); + spl_lang_type_node_t ln = {0}; ln.kind = lk; ln.ir_type_id = agg_ir; - ln.methods = methods; - return spl_lang_node_push(sema->type, &ln); + vec_init(ln.methods); + spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln); + + if (owner_def_id) { + spl_def_node_t *d = spl_def_node(sema->type, owner_def_id); + if (d) + d->lang_id = agg_lang; + } + + spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; + sema->current_aggregate_lang = agg_lang; + + spl_type_member_vec_t members; + vec_init(members); + spl_lang_method_vec_t methods; + vec_init(methods); + + for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { + spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i); + spl_ast_node_t *mn = spl_ast_node(sema->ast, mref); + if (!mn) + continue; + + if (mn->kind == SPL_AST_MEMBER_DECL) { + spl_lang_type_id_t mtid = 0; + if (mn->member_decl.type_expr) + 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 = mref}; + vec_push(members, m); + } else if (mn->kind == SPL_AST_FN_DECL) { + spl_def_id_t fn_def = + spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, sema->ast, mref); + mn->resolved_def_id = fn_def; + spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def); + if (fn_d) + fn_d->owner_def = owner_def_id; + spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def}; + vec_push(methods, meth); + } else if (mn->kind == SPL_AST_TYPE_DECL) { + spl_def_id_t tdef = mn->resolved_def_id; + if (!tdef) + continue; + spl_lang_method_t meth = {.name = mn->type_decl.name, .def_id = tdef}; + vec_push(methods, meth); + } + } + + sema->current_aggregate_lang = saved_agg; + + spl_type_node_t tn = {0}; + tn.kind = tk; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; + if (tk == SPL_TYPE_ENUM) + tn.agg_type.tag_type = spl_type_builder_int(&sema->type->ir, 32, 1); + tn.agg_type.variants = members; + vec_init(members); + spl_lang_define_ir(sema->type, agg_ir, &tn); + + spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang); + if (lslot) { + vec_free(lslot->methods); + lslot->methods = methods; + vec_init(methods); + } + + return agg_lang; +} + +/* 文件 container 建成匿名 struct:FN_DECL / TYPE_DECL / VAR_DECL / CONST_DECL + 进 methods(复用为 names),MEMBER_DECL 进字段。 */ +static spl_lang_type_id_t sema_build_container_aggregate(spl_sema_t *sema, spl_ast_node_t *n, + spl_def_id_t owner_def_id) { + spl_type_id_t agg_ir = spl_lang_reserve_ir(sema->type); + + spl_lang_type_node_t ln = {0}; + ln.kind = SPL_LANG_TYPE_STRUCT; + ln.ir_type_id = agg_ir; + vec_init(ln.methods); + spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &ln); + + if (owner_def_id) { + spl_def_node_t *d = spl_def_node(sema->type, owner_def_id); + if (d) + d->lang_id = agg_lang; + } + + spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; + sema->current_aggregate_lang = agg_lang; + + spl_type_member_vec_t members; + vec_init(members); + spl_lang_method_vec_t methods; + vec_init(methods); + + for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { + spl_ast_node_ref_t dref = vec_at(n->container_members.declarations, i); + spl_ast_node_t *d = spl_ast_node(sema->ast, dref); + if (!d) + continue; + + if (d->kind == SPL_AST_MEMBER_DECL) { + spl_lang_type_id_t mtid = 0; + if (d->member_decl.type_expr) + mtid = sema_infer(sema, d->member_decl.type_expr); + spl_type_member_t m = {.name = d->member_decl.name, + .type_id = spl_lang_type_get_ir_type(sema->type, mtid), + .ast_node_ref = dref}; + vec_push(members, m); + } else if (d->kind == SPL_AST_FN_DECL) { + spl_def_id_t fn_def = d->resolved_def_id; + if (!fn_def) + continue; + spl_def_node_t *fn_d = spl_def_node(sema->type, fn_def); + if (fn_d) + fn_d->owner_def = owner_def_id; + spl_lang_method_t meth = {.name = d->fn_decl.name, .def_id = fn_def}; + vec_push(methods, meth); + } else if (d->kind == SPL_AST_TYPE_DECL) { + spl_def_id_t tdef = d->resolved_def_id; + if (!tdef) + continue; + spl_lang_method_t meth = {.name = d->type_decl.name, .def_id = tdef}; + vec_push(methods, meth); + } else if (d->kind == SPL_AST_VAR_DECL || d->kind == SPL_AST_CONST_DECL) { + spl_def_id_t vdef = d->resolved_def_id; + if (!vdef) + continue; + spl_ast_node_t *pat = spl_ast_node(sema->ast, d->var_const_decl.pattern); + if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) + continue; + spl_lang_method_t meth = {.name = pat->pattern_ident.name, .def_id = vdef}; + vec_push(methods, meth); + } + } + + sema->current_aggregate_lang = saved_agg; + + spl_type_node_t tn = {0}; + tn.kind = SPL_TYPE_STRUCT; + tn.layout.mode = SPL_TYPE_LAYOUT_AUTO; + tn.agg_type.variants = members; + vec_init(members); + spl_lang_define_ir(sema->type, agg_ir, &tn); + + spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang); + if (lslot) { + vec_free(lslot->methods); + lslot->methods = methods; + vec_init(methods); + } + + return agg_lang; +} + +static spl_lang_type_id_t sema_import(spl_sema_t *sema, spl_ast_node_t *n, + spl_ast_node_ref_vec_t *args) { + if (!sema->loader || !sema->loader->load) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_INTERNAL, &n->dbg, + "@import: no module loader configured"); + return 0; + } + if (vec_size(*args) != 1) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_INTRIN_ARG_COUNT, &n->dbg, + "@import expects 1 argument"); + return 0; + } + spl_ast_node_t *arg = spl_ast_node(sema->ast, vec_at(*args, 0)); + if (!arg || arg->kind != SPL_AST_EXPR_STRING_LIT || !arg->string_lit.data) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg, + "@import expects a string literal"); + return 0; + } + const char *path = arg->string_lit.data; + + spl_ast_t *mod_ast = sema->loader->load(sema->loader->user, n->dbg.fname, path, sema->diag); + if (!mod_ast || !mod_ast->root) + return 0; + + spl_ast_node_t *mod_root = spl_ast_node(mod_ast, mod_ast->root); + if (!mod_root || mod_root->kind != SPL_AST_ROOT) + return 0; + spl_ast_node_ref_t cm_ref = mod_root->root.members; + if (!cm_ref) + return 0; + + spl_ast_node_t *cm = spl_ast_node(mod_ast, cm_ref); + if (cm->resolved_def_id) { + spl_def_node_t *d = spl_def_node(sema->type, cm->resolved_def_id); + if (d && d->lang_id) + return d->lang_id; + } + + spl_ast_t *saved_ast = sema->ast; + spl_scope_id_t saved_root = sema->scope->root_scope; + spl_scope_id_t saved_cur = sema->scope->current_scope; + spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; + + sema->ast = mod_ast; + sema->scope->root_scope = 0; + sema->scope->current_scope = 0; + sema->current_aggregate_lang = 0; + + spl_sema_run_module(sema, cm_ref); + + spl_lang_type_id_t t = 0; + spl_ast_node_t *cm_after = spl_ast_node(mod_ast, cm_ref); + if (cm_after->resolved_def_id) + t = sema_eval_decl(sema, cm_after->resolved_def_id); + + sema->ast = saved_ast; + sema->scope->root_scope = saved_root; + sema->scope->current_scope = saved_cur; + sema->current_aggregate_lang = saved_agg; + + return t; } static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) { @@ -364,7 +506,11 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) if (def->state == SPL_DECL_RESOLVED || def->state == SPL_DECL_ERROR) return def->lang_id; + /* RESOLVING 中途但 lang_id 已被 reserve 阶段回填:直接返回。 + A ↔ B 相互引用时 B 引用 A 就走这条短路。 */ if (def->lang_id != 0) { + if (def->state == SPL_DECL_RESOLVING) + return def->lang_id; def->state = SPL_DECL_RESOLVED; return def->lang_id; } @@ -376,9 +522,29 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) return 0; } - def->state = SPL_DECL_RESOLVING; + /* 提前取所有 def 字段:sema_infer_* / sema_build_* 会 push def_table,def 悬垂。 */ + spl_ast_t *owner_ast = def->owner_ast; + spl_def_id_t owner_def_id = def->owner_def; + usize ast_node_ref = def->ast_node_ref; + spl_dbg_node_t dbg_node = def->dbg_node; - spl_ast_node_t *n = spl_ast_node(sema->ast, def->ast_node_ref); + if (!owner_ast) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_INTERNAL, &dbg_node, "def#%zu has no owner_ast", + def_id); + spl_def_node_t *d2 = spl_def_node(sema->type, def_id); + if (d2) + d2->state = SPL_DECL_ERROR; + return 0; + } + + spl_ast_t *saved_ast = sema->ast; + sema->ast = owner_ast; + + def = spl_def_node(sema->type, def_id); + if (def) + def->state = SPL_DECL_RESOLVING; + + spl_ast_node_t *n = spl_ast_node(sema->ast, ast_node_ref); spl_lang_type_id_t result = 0; if (n) { @@ -396,8 +562,8 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) } case SPL_AST_FN_DECL: { spl_lang_type_id_t saved_agg = sema->current_aggregate_lang; - if (def->owner_def) { - spl_def_node_t *owner = spl_def_node(sema->type, def->owner_def); + if (owner_def_id) { + spl_def_node_t *owner = spl_def_node(sema->type, owner_def_id); if (owner && owner->lang_id != 0) sema->current_aggregate_lang = owner->lang_id; } @@ -413,6 +579,10 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) result = sema_infer(sema, n->var_const_decl.init_expr); break; } + case SPL_AST_CONTAINER_MEMBERS: + result = sema_build_container_aggregate(sema, n, def_id); + n->resolved_lang_tid = result; + break; default: break; } @@ -420,9 +590,14 @@ static spl_lang_type_id_t sema_eval_decl(spl_sema_t *sema, spl_def_id_t def_id) spl_def_node_t *final_def = spl_def_node(sema->type, def_id); if (final_def) { - final_def->lang_id = result; + /* reserve 阶段已回填 lang_id 时,即使 result==0(构建失败)也不清掉身份, + 后续引用拿到 ERROR 状态节点而非报环。 */ + if (result != 0) + final_def->lang_id = result; final_def->state = result ? SPL_DECL_RESOLVED : SPL_DECL_ERROR; } + + sema->ast = saved_ast; return result; } @@ -443,7 +618,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema->scope->current_scope = mod_scope; 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); + file_sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, "$file", n->dbg, sema->ast, ref); n->resolved_def_id = file_sym.node; spl_scope_insert(sema->scope, mod_scope, file_sym); @@ -461,9 +636,9 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) { return; } if (te->kind == SPL_AST_TYPE_AGGREGATE) - sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, sym.name, te->dbg, ref); + sym.node = spl_def_alloc(sema->type, SPL_DEF_AGG, sym.name, te->dbg, sema->ast, ref); else - sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, ref); + sym.node = spl_def_alloc(sema->type, SPL_DEF_SCALAR, sym.name, te->dbg, sema->ast, ref); n->resolved_def_id = sym.node; if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, @@ -473,7 +648,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) { } 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); + sym.node = spl_def_alloc(sema->type, SPL_DEF_FN, sym.name, n->dbg, sema->ast, ref); n->resolved_def_id = sym.node; if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, @@ -487,7 +662,7 @@ static void sema_collect_names(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); + sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, sema->ast, ref); n->resolved_def_id = sym.node; if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, @@ -585,7 +760,7 @@ static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, return 0; spl_type_id_t ft = spl_lang_type_get_ir_type(sema->type, src_lang); spl_type_id_t tt = spl_lang_type_get_ir_type(sema->type, dst_lang); - spl_intrin_t expected = spl_intrin_lookup_cast(sema->type, ft, tt); + spl_intrin_t expected = spl_intrin_lookup_cast(&sema->type->ir, ft, tt); if (expected == SPL_INTRIN_NONE) { spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, "`%s`: incompatible types", info->name); @@ -670,10 +845,9 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, if (already == expected) return expected; - /* 已定型 */ if (already != 0) { spl_lang_type_node_t *an = spl_lang_type_node(sema->type, already); - spl_type_node_t *air = an ? spl_type_node(sema->type, an->ir_type_id) : NULL; + spl_type_node_t *air = an ? spl_type_node(&sema->type->ir, an->ir_type_id) : NULL; bool a_rebindable = (an && an->kind == SPL_LANG_TYPE_INFER) || (an && an->kind == SPL_LANG_TYPE_INT && air && air->int_type.bits == 0) || @@ -694,9 +868,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, n->resolved_lang_tid = 0; } - /* 未定型的构造性节点 */ switch (n->kind) { - case SPL_AST_EXPR_UNARY: { if (n->unary.op == SPL_UNARY_OP_ADDRESS || n->unary.op == SPL_UNARY_OP_DEREF) break; @@ -764,7 +936,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, "pointer offset must be integer"); return 0; } - spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id); + spl_type_node_t *rn_ir = spl_type_node(&sema->type->ir, rn->ir_type_id); if (rn_ir && rn_ir->int_type.bits == 0) { spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); @@ -842,7 +1014,7 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, } 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); + spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir); if (!irn) { spl_diag_error(sema->diag, SPL_DIAG_KIND_TYPE_MISMATCH, &n->dbg, "aggregate type unresolved"); @@ -862,7 +1034,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, return 0; } usize idx = 0; - if (!spl_type_agg_member_idx(sema->type, agg_ir, item->struct_init_item.name, &idx)) { + if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name, + &idx)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no variant `%s`", item->struct_init_item.name); return 0; @@ -882,7 +1055,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, 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)) { + if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name, + &idx)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`", item->struct_init_item.name); continue; @@ -925,7 +1099,6 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, break; } - /* 兜底:infer 后按子类型 / comptime 判定 */ spl_lang_type_id_t from = sema_infer(sema, ref); if (!from) return 0; @@ -934,8 +1107,8 @@ static spl_lang_type_id_t sema_coerce(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_lang_type_node_t *from_n = spl_lang_type_node(sema->type, from); spl_lang_type_node_t *to_n = spl_lang_type_node(sema->type, expected); - spl_type_node_t *from_ir = from_n ? spl_type_node(sema->type, from_n->ir_type_id) : NULL; - spl_type_node_t *to_ir = to_n ? spl_type_node(sema->type, to_n->ir_type_id) : NULL; + spl_type_node_t *from_ir = from_n ? spl_type_node(&sema->type->ir, from_n->ir_type_id) : NULL; + spl_type_node_t *to_ir = to_n ? spl_type_node(&sema->type->ir, to_n->ir_type_id) : NULL; bool from_comptime_int = from_n && from_n->kind == SPL_LANG_TYPE_INT && from_ir && from_ir->int_type.bits == 0; @@ -983,7 +1156,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { switch (n->kind) { - /* ---------- 字面量 ---------- */ case SPL_AST_EXPR_INT_LIT: { spl_lang_type_id_t t = spl_lang_make_int(sema->type, 0, 1); n->resolved_lang_tid = t; @@ -1022,7 +1194,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return t; } - /* ---------- IDENT ---------- */ case SPL_AST_EXPR_IDENT: { const char *name = n->ident.name; spl_symbol_t sym; @@ -1042,7 +1213,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return t; } - /* ---------- UNARY ---------- */ case SPL_AST_EXPR_UNARY: { spl_lang_type_id_t op = sema_infer(sema, n->unary.operand); if (op == 0) @@ -1094,7 +1264,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } - /* ---------- BINARY ---------- */ case SPL_AST_EXPR_BINARY: { spl_binary_op_t op = n->binary.op; @@ -1174,7 +1343,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (ln && ln->kind == SPL_LANG_TYPE_PTR && rn && rn->kind == SPL_LANG_TYPE_INT && (op == SPL_OP_ADD || op == SPL_OP_SUB)) { - spl_type_node_t *rn_ir = spl_type_node(sema->type, rn->ir_type_id); + spl_type_node_t *rn_ir = spl_type_node(&sema->type->ir, rn->ir_type_id); if (rn_ir && rn_ir->int_type.bits == 0) { spl_lang_type_id_t it = spl_lang_make_int(sema->type, sizeof(void *) * 8, 1); sema_coerce(sema, n->binary.right, it); @@ -1200,7 +1369,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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) { @@ -1243,8 +1411,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } for (usize i = 0; i < nargs && i < fixed; ++i) { - spl_lang_type_id_t pt = - vec_at(spl_lang_type_node(sema->type, callee_tid)->extra.fn.params, i); + spl_lang_type_node_t *fn2 = spl_lang_type_node(sema->type, callee_tid); + if (!fn2) + return 0; + spl_lang_type_id_t pt = vec_at(fn2->extra.fn.params, i); if (!sema_coerce(sema, vec_at(n->call.args, i), pt)) return 0; } @@ -1261,7 +1431,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); @@ -1287,7 +1456,8 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); if (agg_ir) { - const spl_type_member_t *m = spl_type_agg_member(sema->type, agg_ir, n->field.field); + const spl_type_member_t *m = + spl_type_agg_member(&sema->type->ir, agg_ir, n->field.field); if (m) { spl_lang_type_id_t ft = sema_lang_from_ir(sema, m->type_id); if (!ft) { @@ -1300,12 +1470,18 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } - for (usize i = 0; i < vec_size(agg->methods); ++i) { - spl_lang_method_t *meth = &vec_at(agg->methods, i); - if (strcmp(meth->name, n->field.field) != 0) + const char *fname = n->field.field; + usize nmethods = vec_size(agg->methods); + for (usize i = 0; i < nmethods; ++i) { + spl_lang_type_node_t *agg2 = spl_lang_type_node(sema->type, agg_lang); + if (!agg2) + break; + spl_lang_method_t *meth = &vec_at(agg2->methods, i); + if (strcmp(meth->name, fname) != 0) continue; - n->resolved_def_id = meth->def_id; - spl_lang_type_id_t t = sema_eval_decl(sema, meth->def_id); + spl_def_id_t did = meth->def_id; + n->resolved_def_id = did; + spl_lang_type_id_t t = sema_eval_decl(sema, did); n->resolved_lang_tid = t; return t; } @@ -1315,7 +1491,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } - /* ---------- 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); @@ -1355,7 +1530,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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) @@ -1379,7 +1553,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return s; } - /* ---------- CAST ---------- */ case SPL_AST_EXPR_CAST: { spl_lang_type_id_t dst_lang = sema_infer(sema, n->cast.type); if (!dst_lang) @@ -1389,7 +1562,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; spl_lang_type_node_t *sn = spl_lang_type_node(sema->type, src_lang); - spl_type_node_t *sir = sn ? spl_type_node(sema->type, sn->ir_type_id) : NULL; + spl_type_node_t *sir = sn ? spl_type_node(&sema->type->ir, sn->ir_type_id) : NULL; bool src_is_literal_int = sn && sn->kind == SPL_LANG_TYPE_INT && sir && sir->int_type.bits == 0; bool src_is_literal_float = @@ -1414,7 +1587,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { "as: unresolved source or target type"); return 0; } - spl_intrin_t in = spl_intrin_lookup_cast(sema->type, ft, tt); + spl_intrin_t in = spl_intrin_lookup_cast(&sema->type->ir, ft, tt); if (in == SPL_INTRIN_NONE) { spl_diag_error(sema->diag, SPL_DIAG_KIND_CAST_INVALID, &n->dbg, "as: invalid conversion (not supported by as)"); @@ -1424,7 +1597,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return dst_lang; } - /* ---------- TUPLE ---------- */ case SPL_AST_EXPR_TUPLE: { spl_lang_type_id_vec_t es; vec_init(es); @@ -1437,7 +1609,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return t; } - /* ---------- ARRAY_LIT ---------- */ case SPL_AST_EXPR_ARRAY_LIT: { spl_lang_type_id_t elem_t = 0; if (n->array_literal.elem_type) @@ -1467,7 +1638,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return arr; } - /* ---------- AGGREGATE_LIT ---------- */ case SPL_AST_EXPR_AGGREGATE_LIT: { const char *type_name = n->aggregate_literal.name; if (!type_name) { @@ -1501,7 +1671,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); + spl_type_node_t *irn = spl_type_node(&sema->type->ir, agg_ir); if (irn) { for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { spl_ast_node_t *item = @@ -1509,7 +1679,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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, + if (!spl_type_agg_member_idx(&sema->type->ir, agg_ir, item->struct_init_item.name, &idx)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_NO_FIELD, &item->dbg, "no field `%s`", item->struct_init_item.name); @@ -1525,8 +1695,21 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return agg; } - /* ---------- COMPTIME_CALL ---------- */ case SPL_AST_EXPR_COMPTIME_CALL: { + if (n->comptime_call.name && strcmp(n->comptime_call.name, "import") == 0) { + spl_lang_type_id_t t = sema_import(sema, n, &n->comptime_call.args); + n->resolved_lang_tid = t; + return t; + } + if (n->comptime_call.name && strcmp(n->comptime_call.name, "self") == 0) { + if (sema->current_aggregate_lang == 0) { + spl_diag_error(sema->diag, SPL_DIAG_KIND_UNDEFINED_SYMBOL, &n->dbg, + "`@self` outside of aggregate"); + return 0; + } + n->resolved_lang_tid = sema->current_aggregate_lang; + return sema->current_aggregate_lang; + } spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); if (in == SPL_INTRIN_NONE) { spl_diag_error(sema->diag, SPL_DIAG_KIND_UNKNOWN_INTRIN, &n->dbg, @@ -1538,11 +1721,9 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return t; } - /* ---------- BLOCK ---------- */ case SPL_AST_EXPR_BLOCK: return sema_block_body(sema, n, 0); - /* ---------- IF ---------- */ case SPL_AST_EXPR_IF: { spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); sema_coerce(sema, n->if_expr.cond, bt); @@ -1560,7 +1741,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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) @@ -1623,7 +1803,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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)); + sema->ast, vec_at(n->for_expr.idents, i)); spl_def_resolve(sema->type, sym.node, elem_tid); if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, @@ -1656,7 +1836,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } - /* ---------- FN_TYPE ---------- */ case SPL_AST_EXPR_FN_TYPE: { spl_lang_type_id_vec_t ps; vec_init(ps); @@ -1670,7 +1849,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); @@ -1754,10 +1932,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { n->resolved_lang_tid = sema->current_aggregate_lang; return sema->current_aggregate_lang; } + if (name && strcmp(name, "import") == 0) { + spl_lang_type_id_t t = sema_import(sema, n, &n->type_comptime_call.args); + n->resolved_lang_tid = t; + return t; + } 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)); @@ -1795,7 +1977,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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, + psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg, sema->ast, vec_at(n->fn_decl.params, i)); spl_lang_type_id_t p_tid = sema_infer(sema, pd->param_decl.type_expr); spl_def_node_t *pdef = spl_def_node(sema->type, psym.node); @@ -1845,7 +2027,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return lang; } - /* ---------- 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); @@ -1858,7 +2039,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); + sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, sema->ast, ref); n->resolved_def_id = sym.node; if (!spl_scope_insert(sema->scope, sema->scope->current_scope, sym)) { spl_diag_error(sema->diag, SPL_DIAG_KIND_DUPLICATE_SYMBOL, &n->dbg, @@ -1892,7 +2073,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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); @@ -1902,7 +2082,6 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { 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) @@ -2009,7 +2188,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } -void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope, +void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope, spl_attr_t *attr) { Assert(sema != NULL && ast != NULL && type != NULL && scope != NULL && attr != NULL); sema->ast = ast; @@ -2021,6 +2200,7 @@ void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope sema->attr = attr; sema->root = (spl_symbol_t){0}; vec_init(sema->label_stack); + sema->loader = NULL; sema->diag = NULL; } @@ -2046,6 +2226,10 @@ void spl_sema_run(spl_sema_t *sema) { if (!root || root->kind != SPL_AST_ROOT) return; spl_sema_run_module(sema, root->root.members); + + spl_ast_node_t *cm = spl_ast_node(sema->ast, root->root.members); + if (cm && cm->resolved_def_id) + sema_eval_decl(sema, cm->resolved_def_id); } void spl_sema_dump(spl_sema_t *sema) { @@ -2066,9 +2250,9 @@ void spl_sema_dump(spl_sema_t *sema) { printf("\n"); } printf("TypeTable:\n"); - for (usize i = 1; i < vec_size(sema->type->type_table); ++i) { + for (usize i = 1; i < vec_size(sema->type->ir.type_table); ++i) { printf(" type_id#%zu ", i); - spl_type_pure_dump(sema->type, i); + spl_type_pure_dump(&sema->type->ir, i); printf("\n"); } printf("DefTable:\n"); diff --git a/stage1/spl_sema.h b/stage1/spl_sema.h index 50c0ab0..50e3378 100644 --- a/stage1/spl_sema.h +++ b/stage1/spl_sema.h @@ -4,48 +4,23 @@ #include "spl_ast.h" #include "spl_attr.h" #include "spl_diag.h" +#include "spl_lang_type.h" #include "spl_mpa.h" +#include "spl_scope.h" #include "spl_type.h" -typedef enum { - SPL_SYMBOL_KIND_ERROR, - SPL_SYMBOL_KIND_VAR, - SPL_SYMBOL_KIND_MEMBER, - SPL_SYMBOL_KIND_FN, - SPL_SYMBOL_KIND_TYPE, -} spl_symbol_kind_t; - -typedef struct { - const char *name; - spl_symbol_kind_t kind; - spl_def_id_t node; -} spl_symbol_t; - -typedef usize spl_scope_id_t; /* 0 is error */ - -typedef struct { - spl_scope_id_t parent; - MAP(const char *, spl_symbol_t) symbols; -} spl_scope_node_t; -typedef VEC(spl_scope_node_t) spl_scope_node_vec_t; - -typedef struct { - spl_scope_node_vec_t scopes; - spl_scope_id_t root_scope; - spl_scope_id_t current_scope; -} spl_scope_t; - -void spl_scope_init(spl_scope_t *scope); -void spl_scope_drop(spl_scope_t *scope); -spl_scope_id_t spl_scope_alloc(spl_scope_t *scope); -bool spl_scope_insert(spl_scope_t *scope, spl_scope_id_t id, spl_symbol_t symbol); -bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out); - -typedef VEC(const char *) spl_symbol_path_t; +typedef struct spl_module_loader spl_module_loader_t; +struct spl_module_loader { + /* 从 from_fname 所在目录解析 path;返回该文件的 ast(已 init + parse)。 + 失败(文件不存在 / parse 错误 / 环)返回 NULL。 + loader 拥有 ast 的生命周期;sema 不负责释放。 */ + spl_ast_t *(*load)(void *user, const char *from_fname, const char *path, spl_diag_t *diag); + void *user; +}; typedef struct { spl_ast_t *ast; - spl_type_t *type; + spl_lang_type_t *type; spl_scope_t *scope; spl_symbol_t root; spl_attr_t *attr; @@ -53,11 +28,11 @@ typedef struct { spl_lang_type_id_t current_fn_ret_tid; spl_lang_type_id_t current_loop_break_tid; spl_symbol_path_t label_stack; - + const spl_module_loader_t *loader; spl_diag_t *diag; } spl_sema_t; -void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope, +void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_lang_type_t *type, spl_scope_t *scope, spl_attr_t *attr); void spl_sema_drop(spl_sema_t *sema); diff --git a/stage1/spl_tok.c b/stage1/spl_tok.c new file mode 100644 index 0000000..9c6a091 --- /dev/null +++ b/stage1/spl_tok.c @@ -0,0 +1,15 @@ +#include "spl_tok.h" + +const char *spl_tok_type_name(spl_tok_type_t t) { + static const char *const names[] = { +#define X(name, enum_name, dummy) #enum_name, + KEYWORD_TABLE +#undef X +#define X(name, enum_name, dummy) #enum_name, + TOKEN_TABLE +#undef X + }; + if ((usize)t < sizeof(names) / sizeof(names[0])) + return names[t]; + return "?"; +} diff --git a/stage1/spl_tok.h b/stage1/spl_tok.h index 5c53d73..9f06043 100644 --- a/stage1/spl_tok.h +++ b/stage1/spl_tok.h @@ -127,4 +127,6 @@ typedef struct { typedef VEC(spl_tok_t) spl_tok_vec_t; +const char *spl_tok_type_name(spl_tok_type_t t); + #endif /* __SPL_TOK_H__ */ diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 4f06c11..3d0a09b 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -143,169 +143,24 @@ spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *tn) { spl_type_id_t id = vec_size(type->type_table); vec_push(type->type_table, *tn); map_put_new(type->type_map, hash, id); - // 清空传入节点中的动态成员,防止重复释放 tn->kind = SPL_TYPE_ERROR; return id; } -static usize spl_lang_type_hash(spl_lang_type_node_t n) { - usize hash = (usize)n.kind * 131 + n.ir_type_id; - switch (n.kind) { - case SPL_LANG_TYPE_SLICE: - case SPL_LANG_TYPE_RANGE: - hash += n.extra.elem; - break; - case SPL_LANG_TYPE_TUPLE: - for (usize i = 0; i < vec_size(n.extra.elems); i++) { - hash += vec_at(n.extra.elems, i); - } - break; - case SPL_LANG_TYPE_FN: - hash += n.extra.fn.ret; - for (usize i = 0; i < vec_size(n.extra.fn.params); i++) { - hash += vec_at(n.extra.fn.params, i); - } - break; - case SPL_LANG_TYPE_STRUCT: - case SPL_LANG_TYPE_UNION: - case SPL_LANG_TYPE_ENUM: - case SPL_LANG_TYPE_SHAPE: - for (usize i = 0; i < vec_size(n.methods); i++) { - spl_lang_method_t *m = &vec_at(n.methods, i); - hash += m->def_id * 31; - if (m->name) { - const char *s = m->name; - while (*s) - hash = hash * 31 + (usize)(*s++); - } - } - break; - default: - break; - } - return hash; -} - -static int spl_lang_type_eq(spl_lang_type_node_t n1, spl_lang_type_node_t n2) { - if (n1.kind != n2.kind || n1.ir_type_id != n2.ir_type_id) - return 1; - switch (n1.kind) { - case SPL_LANG_TYPE_SLICE: - case SPL_LANG_TYPE_RANGE: - return n1.extra.elem != n2.extra.elem; - case SPL_LANG_TYPE_TUPLE: - if (vec_size(n1.extra.elems) != vec_size(n2.extra.elems)) - return 1; - for (usize i = 0; i < vec_size(n1.extra.elems); i++) { - if (vec_at(n1.extra.elems, i) != vec_at(n2.extra.elems, i)) - return 1; - } - return 0; - case SPL_LANG_TYPE_FN: - if (n1.extra.fn.ret != n2.extra.fn.ret) - return 1; - if (vec_size(n1.extra.fn.params) != vec_size(n2.extra.fn.params)) - return 1; - for (usize i = 0; i < vec_size(n1.extra.fn.params); i++) { - if (vec_at(n1.extra.fn.params, i) != vec_at(n2.extra.fn.params, i)) - return 1; - } - return 0; - case SPL_LANG_TYPE_STRUCT: - case SPL_LANG_TYPE_UNION: - case SPL_LANG_TYPE_ENUM: - case SPL_LANG_TYPE_SHAPE: - if (vec_size(n1.methods) != vec_size(n2.methods)) - return 1; - for (usize i = 0; i < vec_size(n1.methods); i++) { - spl_lang_method_t *a = &vec_at(n1.methods, i); - spl_lang_method_t *b = &vec_at(n2.methods, i); - if (a->def_id != b->def_id) - return 1; - if ((a->name == NULL) != (b->name == NULL)) - return 1; - if (a->name && strcmp(a->name, b->name) != 0) - return 1; - } - return 0; - default: - return 0; - } -} - -static usize spl_lang_map_hash(usize k) { return MAP_HASH_INT(k); } -static int spl_lang_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } - -static void spl_lang_node_free_extra(spl_lang_type_node_t *n) { - switch (n->kind) { - case SPL_LANG_TYPE_TUPLE: - vec_free(n->extra.elems); - break; - case SPL_LANG_TYPE_FN: - vec_free(n->extra.fn.params); - break; - case SPL_LANG_TYPE_STRUCT: - case SPL_LANG_TYPE_UNION: - case SPL_LANG_TYPE_ENUM: - case SPL_LANG_TYPE_SHAPE: - vec_free(n->methods); - break; - default: - break; - } -} - -spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node) { - usize hash = spl_lang_type_hash(*node); - usize idx = (usize)-1; - spl_lang_type_id_t cand = 0; - while (map_get_continue(type->lang_map, hash, &cand, &idx)) { - spl_lang_type_node_t *existing = &vec_at(type->lang_table, cand); - if (spl_lang_type_eq(*existing, *node) == 0) { - spl_lang_node_free_extra(node); - return cand; - } - } - spl_lang_type_id_t id = vec_size(type->lang_table); - vec_push(type->lang_table, *node); - map_put_new(type->lang_map, hash, id); - node->kind = SPL_LANG_TYPE_ERROR; - return id; -} - void spl_type_init(spl_type_t *type) { vec_init(type->type_table); spl_type_node_t type_node = {0}; vec_push(type->type_table, type_node); map_init(type->type_map, spl_type_map_hash, spl_type_map_cmp); - - vec_init(type->lang_table); - spl_lang_type_node_t lang_type_node = {0}; - vec_push(type->lang_table, lang_type_node); - map_init(type->lang_map, spl_lang_map_hash, spl_lang_map_cmp); - - vec_init(type->def_table); - vec_push(type->def_table, (spl_def_node_t){0}); } void spl_type_drop(spl_type_t *type) { - // 释放底层类型 for (usize i = 0; i < vec_size(type->type_table); i++) { spl_type_node_t *n = &vec_at(type->type_table, i); spl_type_node_free_vecs(n); } map_free(type->type_map); vec_free(type->type_table); - - // 释放语言级类型 - for (usize i = 0; i < vec_size(type->lang_table); i++) { - spl_lang_type_node_t *n = &vec_at(type->lang_table, i); - spl_lang_node_free_extra(n); - } - map_free(type->lang_map); - vec_free(type->lang_table); - - vec_free(type->def_table); } spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id) { @@ -314,18 +169,6 @@ spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id) { return &vec_at(type->type_table, id); } -spl_lang_type_node_t *spl_lang_type_node(const spl_type_t *type, spl_lang_type_id_t id) { - if (!id || id >= vec_size(type->lang_table)) - return NULL; - return &vec_at(type->lang_table, id); -} - -spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id) { - if (!id || id >= vec_size(type->def_table)) - return NULL; - return &vec_at(type->def_table, id); -} - bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super) { if (sub == 0 || super == 0) return false; @@ -337,25 +180,20 @@ bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_ if (!nsub || !nsuper) return false; - // never 是任何类型的子类型 if (nsub->kind == SPL_TYPE_NEVER) return true; - // 任何类型是 any 的子类型 if (nsuper->kind == SPL_TYPE_ANY) return true; - // 数值类型子类型:comptime_int (bits=0) 可适配任何整数 if (nsub->kind == SPL_TYPE_INT && nsuper->kind == SPL_TYPE_INT) { if (nsub->int_type.bits == 0) - return true; // comptime_int 适配任意整数 + return true; if (nsub->int_type.is_signed == nsuper->int_type.is_signed) { return nsub->int_type.bits <= nsuper->int_type.bits; } - // 无符号 → 有符号:目标位数必须大于源位数(需要额外符号位) if (!nsub->int_type.is_signed && nsuper->int_type.is_signed) { return nsuper->int_type.bits > nsub->int_type.bits; } - // 有符号 → 无符号:不允许 return false; } if (nsub->kind == SPL_TYPE_FLOAT && nsuper->kind == SPL_TYPE_FLOAT) { @@ -364,233 +202,91 @@ bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_ return nsub->float_type.bits <= nsuper->float_type.bits; } - // 其他情况:结构等价(已在相等判断中处理) return false; } -bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub, - spl_lang_type_id_t super) { - if (sub == 0 || super == 0) - return false; - if (sub == super) - return true; - - spl_lang_type_node_t *nsub = spl_lang_type_node(type, sub); - spl_lang_type_node_t *nsuper = spl_lang_type_node(type, super); - if (!nsub || !nsuper) - return false; - - /* never 是任何类型的子类型(undefined / null 字面量的 pointee) */ - if (nsub->kind == SPL_LANG_TYPE_NEVER) - return true; - - /* 任何类型是 any 的子类型 */ - if (nsuper->kind == SPL_LANG_TYPE_ANY) - return true; - - /* 整数:只有 comptime_int (bits==0) 能物化到具体整数 */ - if (nsub->kind == SPL_LANG_TYPE_INT && nsuper->kind == SPL_LANG_TYPE_INT) { - spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id); - if (!ir_sub) - return false; - return ir_sub->int_type.bits == 0; +void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { + spl_type_node_t *n = spl_type_node(type, id); + if (!n) { + printf("none"); + return; } - - /* 浮点:只有 comptime_float (bits==0) 能物化到具体浮点 */ - if (nsub->kind == SPL_LANG_TYPE_FLOAT && nsuper->kind == SPL_LANG_TYPE_FLOAT) { - spl_type_node_t *ir_sub = spl_type_node(type, nsub->ir_type_id); - if (!ir_sub) - return false; - return ir_sub->float_type.bits == 0; + switch (n->kind) { + case SPL_TYPE_ERROR: + printf("error"); + break; + 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: + printf("quant"); + break; + case SPL_TYPE_BOOL: + printf("bool"); + break; + case SPL_TYPE_INT: + if (n->int_type.bits == 0) + printf("comptime_int"); + else + printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); + break; + case SPL_TYPE_FLOAT: + if (n->float_type.bits == 0) + printf("comptime_float"); + else + printf("f%zu", n->float_type.bits); + break; + case SPL_TYPE_PTR: + printf("*"); + spl_type_pure_dump(type, n->ptr_type.pointee); + break; + case SPL_TYPE_ARRAY: + printf("[%zu]", n->array_type.len); + spl_type_pure_dump(type, n->array_type.element); + break; + case SPL_TYPE_STRUCT: + case SPL_TYPE_UNION: + case SPL_TYPE_ENUM: + case SPL_TYPE_SHAPE: { + const char *kw = "struct"; + if (n->kind == SPL_TYPE_UNION) + kw = "union"; + else if (n->kind == SPL_TYPE_ENUM) + kw = "enum"; + else if (n->kind == SPL_TYPE_SHAPE) + kw = "shape"; + printf("%s{", kw); + for (usize i = 0; i < vec_size(n->agg_type.variants); i++) { + if (i) + printf(", "); + spl_type_member_t *m = &n->agg_type.variants.data[i]; + printf("%s:", m->name ? m->name : "?"); + spl_type_pure_dump(type, m->type_id); + } + printf("}"); + break; } - - /* 指针:只保留 *never -> *T、*T -> *any、同 elem */ - if (nsub->kind == SPL_LANG_TYPE_PTR && nsuper->kind == SPL_LANG_TYPE_PTR) { - if (nsub->extra.elem == nsuper->extra.elem) - return true; - spl_lang_type_node_t *sub_elem = spl_lang_type_node(type, nsub->extra.elem); - spl_lang_type_node_t *super_elem = spl_lang_type_node(type, nsuper->extra.elem); - if (sub_elem && sub_elem->kind == SPL_LANG_TYPE_NEVER) - return true; - if (super_elem && super_elem->kind == SPL_LANG_TYPE_ANY) - return true; - return false; + case SPL_TYPE_FN: + printf("fn("); + for (usize i = 0; i < vec_size(n->fn_type.params); i++) { + if (i) + printf(","); + spl_type_pure_dump(type, vec_at(n->fn_type.params, i)); + } + printf(")"); + spl_type_pure_dump(type, n->fn_type.ret); + break; } - - return false; -} - -static uint32_t spl_type_std_int_bits_up(uint32_t bits) { - if (bits <= 8) - return 8; - if (bits <= 16) - return 16; - if (bits <= 32) - return 32; - if (bits <= 64) - return 64; - return 0; -} - -spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t a, - spl_lang_type_id_t b) { - if (a == 0 || b == 0) - return 0; - if (a == b) - return a; - - spl_lang_type_node_t *na = spl_lang_type_node(type, a); - spl_lang_type_node_t *nb = spl_lang_type_node(type, b); - if (!na || !nb) - return 0; - - if (na->kind == SPL_LANG_TYPE_NEVER) - return b; - if (nb->kind == SPL_LANG_TYPE_NEVER) - return a; - if (na->kind == SPL_LANG_TYPE_ANY || nb->kind == SPL_LANG_TYPE_ANY) - return spl_lang_make_any((spl_type_t *)type); - - bool a_int = na->kind == SPL_LANG_TYPE_INT; - bool b_int = nb->kind == SPL_LANG_TYPE_INT; - bool a_flt = na->kind == SPL_LANG_TYPE_FLOAT; - bool b_flt = nb->kind == SPL_LANG_TYPE_FLOAT; - - /* int / int:仅 comptime 混具体。两侧都具体则失败 */ - if (a_int && b_int) { - spl_type_node_t *ira = spl_type_node(type, na->ir_type_id); - spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id); - if (!ira || !irb) - return 0; - bool a_ct = ira->int_type.bits == 0; - bool b_ct = irb->int_type.bits == 0; - if (a_ct && b_ct) - return a; - if (a_ct) - return b; - if (b_ct) - return a; - return 0; - } - - /* float / float:同 int 策略 */ - if (a_flt && b_flt) { - spl_type_node_t *ira = spl_type_node(type, na->ir_type_id); - spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id); - if (!ira || !irb) - return 0; - bool a_ct = ira->float_type.bits == 0; - bool b_ct = irb->float_type.bits == 0; - if (a_ct && b_ct) - return a; - if (a_ct) - return b; - if (b_ct) - return a; - return 0; - } - - /* int / float:只有 comptime 混 comptime 才视为 comptime_float */ - if (a_int && b_flt) { - spl_type_node_t *ira = spl_type_node(type, na->ir_type_id); - spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id); - if (ira && irb && ira->int_type.bits == 0 && irb->float_type.bits == 0) - return spl_lang_make_float((spl_type_t *)type, 0); - return 0; - } - if (a_flt && b_int) { - spl_type_node_t *ira = spl_type_node(type, na->ir_type_id); - spl_type_node_t *irb = spl_type_node(type, nb->ir_type_id); - if (ira && irb && ira->float_type.bits == 0 && irb->int_type.bits == 0) - return spl_lang_make_float((spl_type_t *)type, 0); - return 0; - } - - /* 指针:*never 与任意 *T 结合得 *T;*T 与 *any 结合得 *any */ - if (na->kind == SPL_LANG_TYPE_PTR && nb->kind == SPL_LANG_TYPE_PTR) { - if (na->extra.elem == nb->extra.elem) - return a; - - spl_lang_type_node_t *ea = spl_lang_type_node(type, na->extra.elem); - spl_lang_type_node_t *eb = spl_lang_type_node(type, nb->extra.elem); - - /* 一侧 elem 是 never:结果取另一侧 */ - if (ea && ea->kind == SPL_LANG_TYPE_NEVER) - return b; - if (eb && eb->kind == SPL_LANG_TYPE_NEVER) - return a; - - /* 一侧 elem 是 any:结果取 any 那侧 */ - if (ea && ea->kind == SPL_LANG_TYPE_ANY) - return a; - if (eb && eb->kind == SPL_LANG_TYPE_ANY) - return b; - - return 0; - } - - return 0; -} - -bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v) { - spl_lang_type_node_t *nt = spl_lang_type_node(type, target); - if (!nt || nt->kind != SPL_LANG_TYPE_INT) - return false; - spl_type_node_t *ir = spl_type_node(type, nt->ir_type_id); - if (!ir) - return false; - uint32_t bits = (uint32_t)ir->int_type.bits; - if (bits == 0) - return true; - bool target_signed = ir->int_type.is_signed != 0; - /* 字面量是无符号位模式:负号由 unary MINUS 承担 */ - uint64_t uval = v.bits; - - if (target_signed) { - if (bits >= 64) - return true; - uint64_t hi = ((uint64_t)1 << (bits - 1)) - 1; - return uval <= hi; - } - if (bits >= 64) - return true; - uint64_t hi = ((uint64_t)1 << bits) - 1; - return uval <= hi; -} - -spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, - spl_dbg_node_t dbg, usize ast_node_ref) { - spl_def_node_t n = {0}; - n.kind = kind; - n.name = name; - n.dbg_node = dbg; - n.lang_id = 0; - n.ast_node_ref = ast_node_ref; - n.state = SPL_DECL_UNRESOLVED; - n.owner_def = 0; - vec_push(type->def_table, n); - return vec_size(type->def_table) - 1; -} - -void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id) { - spl_def_node_t *d = spl_def_node(type, id); - if (d) - d->lang_id = lang_id; -} - -spl_type_id_t spl_lang_type_get_ir_type(spl_type_t *type, spl_lang_type_id_t lang_id) { - spl_lang_type_node_t *n = spl_lang_type_node(type, lang_id); - return n ? n->ir_type_id : 0; -} - -spl_lang_type_id_t spl_def_get_lang_id(spl_type_t *type, spl_def_id_t def_id) { - spl_def_node_t *d = spl_def_node(type, def_id); - return d ? d->lang_id : 0; -} - -spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id) { - spl_lang_type_id_t lang = spl_def_get_lang_id(type, def_id); - return lang ? spl_lang_type_get_ir_type(type, lang) : 0; } spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx) { @@ -689,8 +385,8 @@ spl_type_id_t spl_type_builder_agg(spl_type_t *type, spl_type_node_kind_t tk, spl_type_node_t tn = {0}; tn.kind = tk; tn.layout = layout; - tn.agg_type.variants = *variants; // 移动所有权 - vec_init(*variants); // 清空源 + tn.agg_type.variants = *variants; + vec_init(*variants); if (tk == SPL_TYPE_ENUM) { tn.agg_type.tag_type = tag_type; } else { @@ -698,484 +394,3 @@ 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); } - -static spl_lang_type_id_t spl_lang_node_simple(spl_type_t *type, spl_lang_type_kind_t lang_kind, - spl_type_id_t ir_type_id) { - spl_lang_type_node_t node = {0}; - node.kind = lang_kind; - node.ir_type_id = ir_type_id; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_error(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_ERROR); - return spl_lang_node_simple(type, SPL_LANG_TYPE_ERROR, ir); -} - -spl_lang_type_id_t spl_lang_make_infer(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_INFER); - return spl_lang_node_simple(type, SPL_LANG_TYPE_INFER, ir); -} - -spl_lang_type_id_t spl_lang_make_never(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_NEVER); - return spl_lang_node_simple(type, SPL_LANG_TYPE_NEVER, ir); -} - -spl_lang_type_id_t spl_lang_make_any(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_ANY); - return spl_lang_node_simple(type, SPL_LANG_TYPE_ANY, ir); -} - -spl_lang_type_id_t spl_lang_make_unit(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_UNIT); - return spl_lang_node_simple(type, SPL_LANG_TYPE_UNIT, ir); -} - -spl_lang_type_id_t spl_lang_make_bool(spl_type_t *type) { - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_BOOL); - return spl_lang_node_simple(type, SPL_LANG_TYPE_BOOL, ir); -} - -spl_lang_type_id_t spl_lang_make_int(spl_type_t *type, usize bits, int is_signed) { - spl_type_id_t ir = spl_type_builder_int(type, bits, is_signed); - return spl_lang_node_simple(type, SPL_LANG_TYPE_INT, ir); -} - -spl_lang_type_id_t spl_lang_make_float(spl_type_t *type, usize bits) { - spl_type_id_t ir = spl_type_builder_float(type, bits); - return spl_lang_node_simple(type, SPL_LANG_TYPE_FLOAT, ir); -} - -spl_lang_type_id_t spl_lang_make_array(spl_type_t *type, spl_lang_type_id_t elem_lang, usize len) { - spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); - if (!elem_ir) - return 0; - spl_type_id_t ir = spl_type_builder_array(type, elem_ir, len); - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_ARRAY; - node.ir_type_id = ir; - node.extra.elem = elem_lang; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_ptr(spl_type_t *type, spl_lang_type_id_t pointee_lang) { - spl_type_id_t pointee_ir = spl_lang_type_get_ir_type(type, pointee_lang); - if (!pointee_ir) - return 0; - spl_type_id_t ir = spl_type_builder_ptr(type, pointee_ir); - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_PTR; - node.ir_type_id = ir; - node.extra.elem = pointee_lang; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_slice(spl_type_t *type, spl_lang_type_id_t elem_lang) { - spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); - if (!elem_ir) - return 0; - - spl_lang_type_id_t ptr_lang = spl_lang_make_ptr(type, elem_lang); - spl_lang_type_id_t usize_lang = spl_lang_make_int(type, sizeof(void *) * 8, 0); - spl_type_id_t ptr_ir = spl_lang_type_get_ir_type(type, ptr_lang); - spl_type_id_t usize_ir = spl_lang_type_get_ir_type(type, usize_lang); - - spl_type_member_vec_t members; - vec_init(members); - spl_type_member_t m1 = {.name = "ptr", .type_id = ptr_ir}; - spl_type_member_t m2 = {.name = "len", .type_id = usize_ir}; - vec_push(members, m1); - vec_push(members, m2); - - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; - spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); - - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_SLICE; - node.ir_type_id = struct_ir; - node.extra.elem = elem_lang; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_tuple(spl_type_t *type, const spl_lang_type_id_t *elems, - usize count) { - spl_type_member_vec_t members; - vec_init(members); - for (usize i = 0; i < count; i++) { - spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elems[i]); - if (!elem_ir) { - vec_free(members); - return 0; - } - char name[32]; - snprintf(name, sizeof(name), "%zu", i); - spl_type_member_t m = {.name = strdup(name), .type_id = elem_ir}; - vec_push(members, m); - } - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; - spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); - // 语言级节点 - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_TUPLE; - node.ir_type_id = struct_ir; - vec_init(node.extra.elems); - for (usize i = 0; i < count; i++) { - vec_push(node.extra.elems, elems[i]); - } - spl_lang_type_id_t id = spl_lang_node_push(type, &node); - if (!id) { - // 如果失败,释放临时成员名?但 strdup 的内存已进入底层类型表,不能释放 - // 这里底层类型表拥有这些字符串,所以没问题 - } - return id; -} - -spl_lang_type_id_t spl_lang_make_range(spl_type_t *type, spl_lang_type_id_t elem_lang) { - spl_type_id_t elem_ir = spl_lang_type_get_ir_type(type, elem_lang); - if (!elem_ir) - return 0; - // 构建 struct { start, end } - spl_type_member_vec_t members; - vec_init(members); - spl_type_member_t m1 = {.name = "start", .type_id = elem_ir}; - spl_type_member_t m2 = {.name = "end", .type_id = elem_ir}; - vec_push(members, m1); - vec_push(members, m2); - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; - spl_type_id_t struct_ir = spl_type_builder_agg(type, SPL_TYPE_STRUCT, &members, 0, layout); - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_RANGE; - node.ir_type_id = struct_ir; - node.extra.elem = elem_lang; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_fn(spl_type_t *type, spl_lang_type_id_t ret_lang, - const spl_lang_type_id_t *params_lang, usize nparams) { - spl_type_id_t ret_ir = spl_lang_type_get_ir_type(type, ret_lang); - if (!ret_ir) - return 0; - spl_type_id_vec_t param_irs; - vec_init(param_irs); - for (usize i = 0; i < nparams; i++) { - spl_type_id_t pir = spl_lang_type_get_ir_type(type, params_lang[i]); - if (!pir) { - vec_free(param_irs); - return 0; - } - vec_push(param_irs, pir); - } - spl_type_id_t fn_ir = spl_type_builder_fn(type, ret_ir, param_irs.data, vec_size(param_irs)); - vec_free(param_irs); - // 语言级节点 - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_FN; - node.ir_type_id = fn_ir; - node.extra.fn.ret = ret_lang; - vec_init(node.extra.fn.params); - for (usize i = 0; i < nparams; i++) { - vec_push(node.extra.fn.params, params_lang[i]); - } - spl_lang_type_id_t id = spl_lang_node_push(type, &node); - return id; -} - -spl_lang_type_id_t spl_lang_make_aggregate(spl_type_t *type, spl_lang_type_kind_t kind, - const char *name, const spl_lang_type_id_t *members_lang, - usize nmembers) { - // 确定底层 kind - spl_type_node_kind_t tk; - switch (kind) { - case SPL_LANG_TYPE_STRUCT: - tk = SPL_TYPE_STRUCT; - break; - case SPL_LANG_TYPE_UNION: - tk = SPL_TYPE_UNION; - break; - case SPL_LANG_TYPE_ENUM: - tk = SPL_TYPE_ENUM; - break; - case SPL_LANG_TYPE_SHAPE: - tk = SPL_TYPE_SHAPE; - break; - default: - return 0; - } - // 构建成员向量(成员名自动生成 "0","1"...) - spl_type_member_vec_t members; - vec_init(members); - for (usize i = 0; i < nmembers; i++) { - spl_type_id_t member_ir = spl_lang_type_get_ir_type(type, members_lang[i]); - if (!member_ir) { - vec_free(members); - return 0; - } - char field_name[32]; - snprintf(field_name, sizeof(field_name), "%zu", i); - spl_type_member_t m = {.name = strdup(field_name), .type_id = member_ir}; - vec_push(members, m); - } - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO, .fixed_align_bits = 0}; - spl_type_id_t agg_ir = spl_type_builder_agg(type, tk, &members, 0, layout); - // 语言级节点(没有额外信息,除了 kind 和 ir_type_id) - spl_lang_type_node_t node = {0}; - node.kind = kind; - node.ir_type_id = agg_ir; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_lang_make_varargs(spl_type_t *type) { - // 底层类型使用 unit(无实际存储),语言级节点单独标记 - spl_type_id_t ir = spl_type_builder_simple(type, SPL_TYPE_UNIT); - spl_lang_type_node_t node = {0}; - node.kind = SPL_LANG_TYPE_VARARGS; - node.ir_type_id = ir; - return spl_lang_node_push(type, &node); -} - -spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name) { - if (!name || !*name) - return 0; - // 简单映射 - if (strcmp(name, "bool") == 0) - return spl_lang_make_bool(type); - if (strcmp(name, "void") == 0) - return spl_lang_make_unit(type); - if (strcmp(name, "isize") == 0) - return spl_lang_make_int(type, sizeof(void *) * 8, 1); - if (strcmp(name, "usize") == 0) - return spl_lang_make_int(type, sizeof(void *) * 8, 0); - if (strcmp(name, "any") == 0) - return spl_lang_make_any(type); - // iN / uN / fN 模式 - char prefix = name[0]; - if (prefix == 'i' || prefix == 'u' || prefix == 'f') { - const char *rest = name + 1; - char *end; - long bits = strtol(rest, &end, 10); - if (end != rest && *end == '\0' && bits > 0) { - if (prefix == 'i') - return spl_lang_make_int(type, (usize)bits, 1); - if (prefix == 'u') - return spl_lang_make_int(type, (usize)bits, 0); - if (prefix == 'f') - return spl_lang_make_float(type, (usize)bits); - } - } - return 0; -} - -void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id) { - spl_type_node_t *n = spl_type_node(type, id); - if (!n) { - printf("none"); - return; - } - switch (n->kind) { - case SPL_TYPE_ERROR: - printf("error"); - break; - 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: - printf("quant"); - break; - case SPL_TYPE_BOOL: - printf("bool"); - break; - case SPL_TYPE_INT: - if (n->int_type.bits == 0) - printf("comptime_int"); - else - printf("%s%zu", n->int_type.is_signed ? "i" : "u", n->int_type.bits); - break; - case SPL_TYPE_FLOAT: - if (n->float_type.bits == 0) - printf("comptime_float"); - else - printf("f%zu", n->float_type.bits); - break; - case SPL_TYPE_PTR: - printf("*"); - spl_type_pure_dump(type, n->ptr_type.pointee); - break; - case SPL_TYPE_ARRAY: - printf("[%zu]", n->array_type.len); - spl_type_pure_dump(type, n->array_type.element); - break; - case SPL_TYPE_STRUCT: - case SPL_TYPE_UNION: - case SPL_TYPE_ENUM: - case SPL_TYPE_SHAPE: { - const char *kw = "struct"; - if (n->kind == SPL_TYPE_UNION) - kw = "union"; - else if (n->kind == SPL_TYPE_ENUM) - kw = "enum"; - else if (n->kind == SPL_TYPE_SHAPE) - kw = "shape"; - printf("%s{", kw); - for (usize i = 0; i < vec_size(n->agg_type.variants); i++) { - if (i) - printf(", "); - spl_type_member_t *m = &n->agg_type.variants.data[i]; - printf("%s:", m->name ? m->name : "?"); - spl_type_pure_dump(type, m->type_id); - } - printf("}"); - break; - } - case SPL_TYPE_FN: - printf("fn("); - for (usize i = 0; i < vec_size(n->fn_type.params); i++) { - if (i) - printf(","); - spl_type_pure_dump(type, vec_at(n->fn_type.params, i)); - } - printf(")"); - spl_type_pure_dump(type, n->fn_type.ret); - break; - } -} - -void spl_lang_type_dump(spl_type_t *type, spl_lang_type_id_t id) { - spl_lang_type_node_t *n = spl_lang_type_node(type, id); - if (!n) { - printf("none"); - return; - } - switch (n->kind) { - case SPL_LANG_TYPE_ERROR: - printf("error"); - break; - case SPL_LANG_TYPE_INFER: - printf("infer"); - break; - case SPL_LANG_TYPE_NEVER: - printf("never"); - break; - case SPL_LANG_TYPE_ANY: - printf("any"); - break; - case SPL_LANG_TYPE_UNIT: - printf("unit"); - break; - case SPL_LANG_TYPE_BOOL: - printf("bool"); - break; - case SPL_LANG_TYPE_VARARGS: - printf("..."); - break; - case SPL_LANG_TYPE_INT: { - spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); - if (tn && tn->int_type.bits == 0) - printf("comptime_int"); - else - spl_type_pure_dump(type, n->ir_type_id); - break; - } - case SPL_LANG_TYPE_FLOAT: { - spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); - if (tn && tn->float_type.bits == 0) - printf("comptime_float"); - else - spl_type_pure_dump(type, n->ir_type_id); - break; - } - case SPL_LANG_TYPE_PTR: - printf("*"); - spl_lang_type_dump(type, n->extra.elem); - break; - case SPL_LANG_TYPE_ARRAY: { - spl_type_node_t *tn = spl_type_node(type, n->ir_type_id); - printf("[%zu]", tn->array_type.len); - spl_type_pure_dump(type, n->ir_type_id); - } break; - case SPL_LANG_TYPE_SLICE: - printf("[]"); - spl_lang_type_dump(type, n->extra.elem); - break; - case SPL_LANG_TYPE_TUPLE: - printf("("); - for (usize i = 0; i < vec_size(n->extra.elems); i++) { - if (i) - printf(","); - spl_lang_type_dump(type, vec_at(n->extra.elems, i)); - } - printf(")"); - break; - case SPL_LANG_TYPE_RANGE: - spl_lang_type_dump(type, n->extra.elem); - printf(".."); - spl_lang_type_dump(type, n->extra.elem); - break; - case SPL_LANG_TYPE_FN: - printf("fn("); - for (usize i = 0; i < vec_size(n->extra.fn.params); i++) { - if (i) - printf(","); - spl_lang_type_dump(type, vec_at(n->extra.fn.params, i)); - } - printf(")"); - spl_lang_type_dump(type, n->extra.fn.ret); - break; - case SPL_LANG_TYPE_STRUCT: - case SPL_LANG_TYPE_UNION: - case SPL_LANG_TYPE_ENUM: - case SPL_LANG_TYPE_SHAPE: - spl_type_pure_dump(type, n->ir_type_id); - break; - } -} - -void spl_type_def_dump(spl_type_t *type, spl_def_id_t id) { - spl_def_node_t *node = spl_def_node(type, id); - if (!node) { - printf("none"); - return; - } - const char *def_kind_name = "unknown"; - switch (node->kind) { - case SPL_DEF_ERROR: - def_kind_name = "error"; - break; - case SPL_DEF_SCALAR: - def_kind_name = "scalar"; - break; - case SPL_DEF_MEMBER: - def_kind_name = "member"; - break; - case SPL_DEF_VAR: - def_kind_name = "var"; - break; - case SPL_DEF_FN: - def_kind_name = "fn"; - break; - case SPL_DEF_AGG: - def_kind_name = "agg"; - break; - case SPL_DEF_BUILTIN: - def_kind_name = "builtin"; - break; - case SPL_DEF_DISTINCT: - def_kind_name = "distinct"; - break; - case SPL_DEF_ALIAS: - def_kind_name = "alias"; - break; - } - printf("kind=%s lang_id=%zu name=%s", def_kind_name, node->lang_id, - node->name ? node->name : "?"); -} \ No newline at end of file diff --git a/stage1/spl_type.h b/stage1/spl_type.h index e22b122..15f6be8 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -2,15 +2,9 @@ #define __SPL_TYPE_H__ #include "../stage0/include/utils.h" -#include "spl_dbg.h" -#include "spl_mpa.h" -typedef usize spl_type_id_t; /* 0 is error */ +typedef usize spl_type_id_t; typedef VEC(spl_type_id_t) spl_type_id_vec_t; -typedef usize spl_lang_type_id_t; /* 0 is error */ -typedef VEC(spl_lang_type_id_t) spl_lang_type_id_vec_t; -typedef usize spl_def_id_t; /* 0 is error */ -typedef VEC(spl_def_id_t) spl_def_id_vec_t; typedef enum { SPL_TYPE_ERROR, @@ -46,13 +40,13 @@ typedef struct { typedef struct { const char *name; spl_type_id_t type_id; - usize ast_node_ref; // 回 AST member_decl 节点引用 dbg/IDE 定位用 不参与 hash + usize ast_node_ref; } spl_type_member_t; typedef VEC(spl_type_member_t) spl_type_member_vec_t; typedef struct { spl_type_node_kind_t kind; - spl_type_layout_t layout; // attribute + spl_type_layout_t layout; union { struct { usize bits; @@ -71,135 +65,30 @@ typedef struct { struct { spl_type_member_vec_t variants; spl_type_id_t tag_type; - } agg_type; // adt record + } agg_type; 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; -typedef enum { - SPL_LANG_TYPE_ERROR, - SPL_LANG_TYPE_INFER, - SPL_LANG_TYPE_NEVER, - SPL_LANG_TYPE_ANY, - SPL_LANG_TYPE_UNIT, - SPL_LANG_TYPE_BOOL, - SPL_LANG_TYPE_INT, - SPL_LANG_TYPE_FLOAT, - SPL_LANG_TYPE_PTR, - SPL_LANG_TYPE_ARRAY, - SPL_LANG_TYPE_SLICE, - SPL_LANG_TYPE_TUPLE, - SPL_LANG_TYPE_RANGE, - SPL_LANG_TYPE_FN, - SPL_LANG_TYPE_STRUCT, - SPL_LANG_TYPE_UNION, - SPL_LANG_TYPE_ENUM, - SPL_LANG_TYPE_SHAPE, - SPL_LANG_TYPE_VARARGS, -} spl_lang_type_kind_t; - -typedef struct { - const char *name; - spl_def_id_t def_id; -} spl_lang_method_t; -typedef VEC(spl_lang_method_t) spl_lang_method_vec_t; - -typedef struct { - spl_lang_type_kind_t kind; - spl_type_id_t ir_type_id; - spl_lang_method_vec_t methods; - union { - spl_lang_type_id_t elem; - spl_lang_type_id_vec_t elems; - struct { - spl_lang_type_id_vec_t params; - spl_lang_type_id_t ret; - } fn; - } extra; -} spl_lang_type_node_t; -typedef VEC(spl_lang_type_node_t) spl_lang_type_vec_t; -typedef MAP(usize, spl_lang_type_id_t) spl_lang_type_map_t; - -typedef enum { - SPL_DEF_ERROR, - SPL_DEF_SCALAR, - SPL_DEF_MEMBER, - SPL_DEF_VAR, - SPL_DEF_FN, - SPL_DEF_AGG, - SPL_DEF_DISTINCT, - SPL_DEF_ALIAS, - SPL_DEF_BUILTIN, -} spl_def_node_kind_t; - -typedef enum { - SPL_DECL_UNRESOLVED, - SPL_DECL_RESOLVING, - SPL_DECL_RESOLVED, - SPL_DECL_ERROR, -} spl_decl_state_t; - -typedef struct { - spl_def_node_kind_t kind; - const char *name; - spl_dbg_node_t dbg_node; - spl_lang_type_id_t lang_id; - usize ast_node_ref; - spl_decl_state_t state; - spl_def_id_t owner_def; -} spl_def_node_t; -typedef VEC(spl_def_node_t) spl_def_node_vec_t; - typedef MAP(usize, spl_type_id_t) spl_type_node_map_t; + typedef struct { spl_type_node_vec_t type_table; spl_type_node_map_t type_map; - spl_lang_type_vec_t lang_table; - spl_lang_type_map_t lang_map; - spl_def_node_vec_t def_table; } spl_type_t; void spl_type_init(spl_type_t *type); void spl_type_drop(spl_type_t *type); -void spl_type_def_dump(spl_type_t *type, spl_def_id_t id); -void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); -void spl_lang_type_dump(spl_type_t *type, spl_lang_type_id_t id); - spl_type_node_t *spl_type_node(const spl_type_t *type, spl_type_id_t id); -spl_lang_type_node_t *spl_lang_type_node(const spl_type_t *type, spl_lang_type_id_t id); -spl_def_node_t *spl_def_node(const spl_type_t *type, spl_def_id_t id); - -bool spl_lang_type_is_subtype(const spl_type_t *type, spl_lang_type_id_t sub, - spl_lang_type_id_t super); -bool spl_type_is_subtype(const spl_type_t *type, spl_type_id_t sub, spl_type_id_t super); -spl_lang_type_id_t spl_lang_node_push(spl_type_t *type, spl_lang_type_node_t *node); - -spl_lang_type_id_t spl_lang_type_join(const spl_type_t *type, spl_lang_type_id_t a, - spl_lang_type_id_t b); - -bool spl_lang_mpa_int_fits(const spl_type_t *type, spl_lang_type_id_t target, spl_mpa_int_t v); - -spl_def_id_t spl_def_alloc(spl_type_t *type, spl_def_node_kind_t kind, const char *name, - spl_dbg_node_t dbg, usize ast_node_ref); -void spl_def_resolve(spl_type_t *type, spl_def_id_t id, spl_lang_type_id_t lang_id); - -spl_type_id_t spl_lang_type_get_ir_type(spl_type_t *type, spl_lang_type_id_t lang_id); -spl_lang_type_id_t spl_def_get_lang_id(spl_type_t *type, spl_def_id_t def_id); -spl_type_id_t spl_def_get_type_id(spl_type_t *type, spl_def_id_t def_id); - -spl_type_id_t spl_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx); -const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, const char *name); -bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *name, usize *out_idx); - spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t *type_node); + spl_type_id_t spl_type_builder_simple(spl_type_t *type, spl_type_node_kind_t kind); 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); @@ -211,27 +100,12 @@ 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_lang_type_id_t spl_lang_make_error(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_infer(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_never(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_any(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_unit(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_bool(spl_type_t *type); -spl_lang_type_id_t spl_lang_make_int(spl_type_t *type, usize bits, int is_signed); -spl_lang_type_id_t spl_lang_make_float(spl_type_t *type, usize bits); -spl_lang_type_id_t spl_lang_make_ptr(spl_type_t *type, spl_lang_type_id_t pointee); -spl_lang_type_id_t spl_lang_make_array(spl_type_t *type, spl_lang_type_id_t elem, usize len); -spl_lang_type_id_t spl_lang_make_slice(spl_type_t *type, spl_lang_type_id_t elem); -spl_lang_type_id_t spl_lang_make_tuple(spl_type_t *type, const spl_lang_type_id_t *elems, - usize count); -spl_lang_type_id_t spl_lang_make_range(spl_type_t *type, spl_lang_type_id_t elem); -spl_lang_type_id_t spl_lang_make_fn(spl_type_t *type, spl_lang_type_id_t ret, - const spl_lang_type_id_t *params, usize nparams); -spl_lang_type_id_t spl_lang_make_aggregate(spl_type_t *type, spl_lang_type_kind_t kind, - const char *name, const spl_lang_type_id_t *members, - usize nmembers); -spl_lang_type_id_t spl_lang_make_varargs(spl_type_t *type); +void spl_type_pure_dump(spl_type_t *type, spl_type_id_t id); -spl_lang_type_id_t spl_type_lookup_builtin(spl_type_t *type, const char *name); +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_type_fn_param_tid(spl_type_t *type, spl_type_id_t fn_tid, usize idx); +const spl_type_member_t *spl_type_agg_member(spl_type_t *type, spl_type_id_t tid, const char *name); +bool spl_type_agg_member_idx(spl_type_t *type, spl_type_id_t tid, const char *name, usize *out_idx); #endif /* __SPL_TYPE_H__ */ diff --git a/stage1/splc0.c b/stage1/splc0.c index 54b4025..5f04111 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -1,7 +1,7 @@ /* splc0.c - SPL compiler CLI (stage 1, 引导用) * - * splc0 --dump tokens|ast|all dump 前端产物 - * splc0 编译 (阶段 B 实现) + * splc0 --dump tokens|ast|sema|ir|vm dump 前端产物 + * splc0 编译 */ #define __SCC_LOG_IMPL_IMPORT_SRC__ #include "../stage0/include/utils.h" @@ -27,6 +27,24 @@ typedef enum { DUMP_VM, } dump_t; +typedef struct { + spl_ast_t *ast; + char *abs_path; + char *src; +} spl_driver_module_t; +typedef VEC(spl_driver_module_t) spl_driver_module_vec_t; + +typedef struct { + spl_ast_t main_ast; + spl_tok_vec_t main_toks; + char *main_path; + + spl_driver_module_vec_t modules; + MAP(const char *, usize) path_to_idx; + + spl_diag_t *diag; +} spl_driver_t; + static char *read_file(const char *path, long *out_len) { FILE *f = fopen(path, "rb"); if (!f) { @@ -42,132 +60,245 @@ static char *read_file(const char *path, long *out_len) { fclose(f); return NULL; } - fread(buf, 1, (size_t)len, f); + size_t nread = fread(buf, 1, (size_t)len, f); fclose(f); - buf[len] = '\0'; - *out_len = len; + buf[nread] = '\0'; + if (out_len) + *out_len = (long)nread; return buf; } -static const char *const tok_type_names[] = { -#define X(name, enum_name, dummy) #enum_name, - KEYWORD_TABLE -#undef X -#define X(name, enum_name, dummy) #enum_name, - TOKEN_TABLE -#undef X -}; - +/* 注意:按值接收,内部 vec_free 释放与调用方共享的 data 指针。 + 调用后原 vec 视为已消费,不要再使用。 */ static void dump_tokens(spl_tok_vec_t toks) { printf("tokens got (%zu)\n", toks.size); for (usize i = 0; i < toks.size; i++) { const spl_tok_t *t = &toks.data[i]; - printf("[%s] %.*s (%zu:%zu)\n", tok_type_names[t->type], (int)t->len, t->lexeme, t->line, + printf("[%s] %.*s (%zu:%zu)\n", spl_tok_type_name(t->type), (int)t->len, t->lexeme, t->line, t->col); } vec_free(toks); } +/* 把 import_path 拼接到 importing_file 所在目录。 + from_fname 为空时按相对 cwd 处理。绝对路径直接透传。 */ +static void resolve_relative(const char *from, const char *path, char *out, usize cap) { + if (!from || !path) { + if (cap) + out[0] = 0; + return; + } + if (path[0] == '/' || path[0] == '\\' || (path[0] && path[1] == ':')) { + snprintf(out, cap, "%s", path); + return; + } + const char *last_sep = NULL; + for (const char *p = from; *p; ++p) + if (*p == '/' || *p == '\\') + last_sep = p; + if (!last_sep) { + snprintf(out, cap, "%s", path); + return; + } + usize dir_len = (usize)(last_sep - from) + 1; + snprintf(out, cap, "%.*s%s", (int)dir_len, from, path); +} + +static spl_ast_t *driver_load(void *user, const char *from_fname, const char *path, + spl_diag_t *diag) { + spl_driver_t *d = user; + char abs[1024]; + resolve_relative(from_fname, path, abs, sizeof abs); + + usize idx; + if (map_get(d->path_to_idx, abs, &idx)) { + spl_ast_t *a = vec_at(d->modules, idx).ast; + if (!a) { + spl_diag_error(diag, SPL_DIAG_KIND_CIRCULAR_DEP, NULL, "circular import: `%s`", abs); + return NULL; + } + return a; + } + + /* 先登记 ast=NULL 占位:若后续解析过程中又有 @import 指回本路径, + 会命中这里,判定为环。 */ + char *key = strdup(abs); + idx = vec_size(d->modules); + spl_driver_module_t placeholder = {.ast = NULL, .abs_path = key, .src = NULL}; + vec_push(d->modules, placeholder); + map_put(d->path_to_idx, key, idx); + + long len = 0; + char *src = read_file(abs, &len); + if (!src) { + spl_diag_error(diag, SPL_DIAG_KIND_LEX_UNEXPECTED, NULL, "@import: cannot open `%s`", abs); + return NULL; + } + (void)len; + + /* key 同时用作 lexer 的 fname:token.fname 与 map key 共享一份 strdup, + 减少一次分配;cleanup 时只 free module.abs_path */ + spl_tok_vec_t toks = spl_lex(src, key); + spl_ast_t *ast = malloc(sizeof *ast); + spl_ast_init(ast, &toks); + ast->diag = diag; + spl_ast_parse(ast); + + vec_at(d->modules, idx).ast = ast; + vec_at(d->modules, idx).src = src; + return ast; +} + static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug, dump_t dump) { (void)gen_debug; - spl_tok_vec_t toks = spl_lex(src, fname); - if (dump == DUMP_TOKEN) { - dump_tokens(toks); - // memory leak - return 0; - } - spl_diag_t diag; spl_diag_init(&diag, stderr); - spl_ast_t ast; - spl_ast_init(&ast, &toks); - spl_diag_set_stage(&diag, SPL_STAGE_PARSE); - ast.diag = &diag; - spl_ast_parse(&ast); - if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { - spl_diag_summary(&diag); - // memory leak - return 1; - } - // spl_ast_valid(&ast); TODO - if (dump == DUMP_AST) { - spl_ast_dump(&ast, ast.root); - // memory leak + spl_driver_t drv = {0}; + drv.diag = &diag; + drv.main_path = strdup(fname); + drv.main_toks = spl_lex(src, drv.main_path); + spl_ast_init(&drv.main_ast, &drv.main_toks); + drv.main_ast.diag = &diag; + map_init(drv.path_to_idx, MAP_HASH_STR, MAP_CMP_STR); + vec_init(drv.modules); + + int rc = 0; + + /* dump_tokens 消费 drv.main_toks(共享 data),之后 main_ast.input 悬空, + 所以这条分支必须在 spl_ast_parse 之前、且不能再 drop main_ast。 */ + if (dump == DUMP_TOKEN) { + dump_tokens(drv.main_toks); + free(drv.main_path); + map_free(drv.path_to_idx); + spl_diag_drop(&diag); return 0; } spl_attr_t attr; - spl_attr_init(&attr); - spl_sema_t sema; - spl_type_t type; + spl_lang_type_t lang_type; spl_scope_t scope; - spl_type_init(&type); + spl_sema_t sema; + spl_ast2ir_t a2ir; + spl_ir_builder_t ir_builder; + spl_ir2vm_t ir2vm; + spl_ast_ptr_vec_t all_asts; + + int attr_ok = 0, lang_type_ok = 0, scope_ok = 0; + int sema_ok = 0, a2ir_ok = 0, irb_ok = 0, ir2vm_ok = 0; + + spl_diag_set_stage(&diag, SPL_STAGE_PARSE); + spl_ast_parse(&drv.main_ast); + if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { + spl_diag_summary(&diag); + rc = 1; + goto cleanup; + } + if (dump == DUMP_AST) { + spl_ast_dump(&drv.main_ast, drv.main_ast.root); + goto cleanup; + } + + spl_attr_init(&attr); + attr_ok = 1; + spl_lang_type_init(&lang_type); + lang_type_ok = 1; spl_scope_init(&scope); - spl_sema_init(&sema, &ast, &type, &scope, &attr); - sema.ast = * + scope_ok = 1; + + spl_sema_init(&sema, &drv.main_ast, &lang_type, &scope, &attr); + sema_ok = 1; + spl_module_loader_t loader = {.load = driver_load, .user = &drv}; + sema.loader = &loader; spl_diag_set_stage(&diag, SPL_STAGE_SEMA); sema.diag = &diag; spl_sema_run(&sema); if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { - // memory leak spl_diag_summary(&diag); - return 1; + rc = 1; + goto cleanup; } if (dump == DUMP_SEMA) { spl_sema_dump(&sema); - spl_ast_dump(&ast, ast.root); - // memory leak - return 0; + spl_ast_dump(&drv.main_ast, drv.main_ast.root); + goto cleanup; } - spl_ast2ir_t a2ir; - spl_ir_builder_t ir_builder; + /* 收集所有 ast:主文件在前,被 import 的文件按加载顺序在后。 + ast2ir 内部会 vec_free(all_asts)。 */ + vec_init(all_asts); + vec_push(all_asts, &drv.main_ast); + for (usize i = 0; i < vec_size(drv.modules); ++i) + vec_push(all_asts, vec_at(drv.modules, i).ast); + spl_ir_builder_init(&ir_builder); + irb_ok = 1; spl_ast2ir_init(&a2ir, &ir_builder, &sema); + a2ir_ok = 1; spl_diag_set_stage(&diag, SPL_STAGE_AST2IR); a2ir.diag = &diag; - spl_ast2ir_run(&a2ir); + spl_ast2ir_run(&a2ir, all_asts); if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { spl_diag_summary(&diag); - // memory leak - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - return 1; + rc = 1; + goto cleanup; } if (dump == DUMP_IR) { - spl_ir_dump(&ir_builder.ir, &type, &attr); - // memory leak - return 0; + spl_ir_dump(&ir_builder.ir, &lang_type.ir, &attr); + goto cleanup; } - spl_ir2vm_t ir2vm; - spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr); - // ir2vm.diag = &diag; + spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &lang_type.ir, &attr); + ir2vm_ok = 1; spl_diag_set_stage(&diag, SPL_STAGE_IR2VM); ir2vm.diag = &diag; - int rc = spl_ir2vm_run(&ir2vm); + rc = spl_ir2vm_run(&ir2vm); if (spl_diag_has_error(&diag) || spl_diag_has_fatal(&diag)) { spl_diag_summary(&diag); - return rc; + goto cleanup; } if (dump == DUMP_VM) { spl_prog_dump(&ir2vm.prog); - // memory leak - return 0; + goto cleanup; } spl_prog_store_to_file(outpath, &ir2vm.prog); + rc = 0; - spl_ir2vm_drop(&ir2vm); - spl_ast2ir_drop(&a2ir); - spl_sema_drop(&sema); - spl_ast_drop(&ast); - // memory leak - return 0; +cleanup: + if (ir2vm_ok) + spl_ir2vm_drop(&ir2vm); + if (a2ir_ok) + spl_ast2ir_drop(&a2ir); + if (irb_ok) + spl_ir_builder_drop(&ir_builder); + if (sema_ok) + spl_sema_drop(&sema); + if (scope_ok) + spl_scope_drop(&scope); + if (lang_type_ok) + spl_lang_type_drop(&lang_type); + if (attr_ok) + spl_attr_drop(&attr); + + spl_ast_drop(&drv.main_ast); + for (usize i = 0; i < vec_size(drv.modules); ++i) { + spl_ast_t *a = vec_at(drv.modules, i).ast; + if (a) { + spl_ast_drop(a); + free(a); + } + free(vec_at(drv.modules, i).abs_path); + free(vec_at(drv.modules, i).src); + } + vec_free(drv.modules); + /* map 的 key 是 module 里 strdup 出的 abs_path,已随 module 释放 */ + map_free(drv.path_to_idx); + free(drv.main_path); + spl_diag_drop(&diag); + return rc; } int main(int argc, char **argv) { @@ -194,20 +325,20 @@ int main(int argc, char **argv) { } const char *flags = argv[argi + 1]; - if (strstr(flags, "lex") != NULL) { + if (strcmp(flags, "lex") == 0) { dump = DUMP_TOKEN; - } else if (strstr(flags, "ast") != NULL) { + } else if (strcmp(flags, "ast") == 0) { dump = DUMP_AST; - } else if (strstr(flags, "sema") != NULL) { + } else if (strcmp(flags, "sema") == 0) { dump = DUMP_SEMA; - } else if (strstr(flags, "ir") != NULL) { + } else if (strcmp(flags, "ir") == 0) { dump = DUMP_IR; - } else if (strstr(flags, "vm") != NULL) { + } else if (strcmp(flags, "vm") == 0) { dump = DUMP_VM; - } else if (strstr(flags, "none") != NULL) { + } else if (strcmp(flags, "none") == 0) { dump = DUMP_NONE; } else { - Panic("--dump unknown flags"); + LOG_FATAL("splc0: --dump takes one of lex|ast|sema|ir|vm|none, got `%s`", flags); return 1; } argi += 2;