From 72ae6d6994241ca4391334ea29a4e48465d9176c Mon Sep 17 00:00:00 2001 From: zzy <2450266535@qq.com> Date: Sun, 13 Sep 2026 22:26:41 +0800 Subject: [PATCH] =?UTF-8?q?stage1=20=E4=BD=BF=E7=94=A8=E5=88=87=E7=89=87?= =?UTF-8?q?=E8=A1=A8=E8=BE=BE=E5=AD=97=E7=AC=A6=E4=B8=B2=E8=80=8C=E9=9D=9E?= =?UTF-8?q?C=E5=AD=97=E7=AC=A6=E4=B8=B2=20=E6=8F=90=E4=BE=9B=E5=B1=9E?= =?UTF-8?q?=E6=80=A7=E7=B3=BB=E7=BB=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- nob.c | 3 +- stage0/spl_mcode.c | 5 +- stage1/spl_ast.c | 16 +- stage1/spl_ast.h | 4 + stage1/spl_ast2ir.c | 79 ++- stage1/spl_attr.c | 152 ++++++ stage1/spl_attr.h | 84 +++ stage1/spl_ir.c | 52 +- stage1/spl_ir.h | 33 +- stage1/spl_ir2vm.c | 241 ++++++--- stage1/spl_ir2vm.h | 6 +- stage1/spl_sema.c | 1250 ++++--------------------------------------- stage1/spl_sema.h | 6 +- stage1/splc0.c | 10 +- 14 files changed, 685 insertions(+), 1256 deletions(-) create mode 100644 stage1/spl_attr.c create mode 100644 stage1/spl_attr.h diff --git a/nob.c b/nob.c index d1da8cc..2f99bfb 100644 --- a/nob.c +++ b/nob.c @@ -27,6 +27,7 @@ static const char *splc0_srcs[] = { "stage1/spl_ast.c", "stage1/spl_dumptree.c", "stage1/spl_type.c", + "stage1/spl_attr.c", "stage1/spl_sema.c", "stage1/spl_intrin.c", "stage1/spl_ir.c", @@ -245,7 +246,7 @@ static bool test_once(const char *fname, void *user_data) { parse_expect(fname, &expect); if (expect.exit_code != result.exit_code) { - nob_log(NOB_ERROR, "Expect code `%d`, Result code `%d`\n", expect.exit_code, + nob_log(NOB_ERROR, "Expect code `%d`, Result code `%d`", expect.exit_code, result.exit_code); return false; } diff --git a/stage0/spl_mcode.c b/stage0/spl_mcode.c index e7cdddf..18f246b 100644 --- a/stage0/spl_mcode.c +++ b/stage0/spl_mcode.c @@ -20,6 +20,7 @@ void spl_prog_init(spl_prog_t *prog) { vec_init(prog->strtab); vec_init(prog->gdata); map_init(prog->symtab, MAP_HASH_STR, MAP_CMP_STR); + prog->debug = NULL; } void spl_prog_drop(spl_prog_t *prog) { @@ -39,7 +40,9 @@ void spl_prog_drop(spl_prog_t *prog) { vec_for(prog->strtab, i) { free((void *)vec_at(prog->strtab, i)); } vec_free(prog->strtab); map_free(prog->symtab); - free(prog->debug); + if (prog->debug) { + free(prog->debug); + } prog->debug = NULL; } diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 4018c75..01f01dc 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -92,6 +92,7 @@ static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const n.kind = kind; n.resolved_def_id = 0; n.resolved_lang_tid = 0; + vec_init(n.attrs); if (tok) { n.dbg.dbg_name = spl_ast_kind_name(kind); n.dbg.fname = tok->fname; @@ -199,13 +200,15 @@ static char parse_char_literal(const spl_tok_t *t) { return c; } -static char *parse_string_literal(parser_t *p, const spl_tok_t *t) { +static char *parse_string_literal(parser_t *p, const spl_tok_t *t, usize *out_len) { const char *src = t->lexeme + 1; const char *end = t->lexeme + t->len - 1; usize cap = t->len + 1; char *tmp = malloc(cap); - if (!tmp) + if (!tmp) { + *out_len = 0; return NULL; + } char *dst = tmp; while (src < end) { char c; @@ -216,7 +219,7 @@ static char *parse_string_literal(parser_t *p, const spl_tok_t *t) { src++; } } - *dst = '\0'; + *out_len = (usize)(dst - tmp); char *interned = intern_string(p->ast, tmp, dst - tmp); free(tmp); return interned; @@ -1402,7 +1405,11 @@ static spl_ast_node_ref_t parse_primary(parser_t *p) { case TOK_STRING_LITERAL: { advance(p); spl_ast_node_ref_t ref = new_node(p, SPL_AST_EXPR_STRING_LIT, t); - node_at(p->ast, ref)->string_lit.data = parse_string_literal(p, t); + usize len = 0; + const char *data = parse_string_literal(p, t, &len); + spl_ast_node_t *node = node_at(p->ast, ref); + node->string_lit.data = data; + node->string_lit.len = len; return ref; } case KW_TRUE: @@ -2234,6 +2241,7 @@ void spl_ast_drop(spl_ast_t *ast) { return; vec_for(ast->str_buckets, idx) { free(vec_at(ast->str_buckets, idx)); } vec_free(ast->str_buckets); + vec_for(ast->node_buckets, idx) { vec_free(vec_at(ast->node_buckets, idx).attrs); } vec_free(ast->node_buckets); vec_free(ast->input); ast->parsed = 0; diff --git a/stage1/spl_ast.h b/stage1/spl_ast.h index 889b6e7..b4f072c 100644 --- a/stage1/spl_ast.h +++ b/stage1/spl_ast.h @@ -6,6 +6,8 @@ #include "spl_lexer.h" #include "spl_tok.h" +#include "spl_attr.h" + /* clang-format off */ #define SPL_AST_KIND_TABLE \ X(SPL_AST_NONE, V0, none) \ @@ -154,6 +156,7 @@ struct spl_ast_node { usize resolved_def_id; usize resolved_lang_tid; usize expected_lang_tid; + spl_attr_id_vec_t attrs; union { /* SPL_AST_ROOT */ @@ -299,6 +302,7 @@ struct spl_ast_node { } char_lit; struct { const char *data; + usize len; } string_lit; struct { bool val; diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 477167d..0a787ee 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -38,6 +38,26 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, static spl_ir_node_ref_t ast2ir_intrin_field(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in); static spl_ir_node_ref_t ast2ir_intrin_len(spl_ast2ir_t *a, spl_ast_node_t *n); +static void copy_attrs_to_ir_node(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t ir_ref) { + if (!ir_ref || !n || vec_size(n->attrs) == 0) + return; + spl_ir_node_t *irn = spl_ir_node(&a->ir->ir, a->ir->current_fn, ir_ref); + if (!irn) + return; + for (usize i = 0; i < vec_size(n->attrs); ++i) + vec_push(irn->attrs, vec_at(n->attrs, i)); +} + +static void copy_attrs_to_ir_func(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_func_ref_t fn_ref) { + if (!fn_ref || !n || vec_size(n->attrs) == 0) + return; + spl_ir_func_t *irf = spl_ir_func(&a->ir->ir, fn_ref); + if (!irf) + return; + for (usize i = 0; i < vec_size(n->attrs); ++i) + vec_push(irf->attrs, vec_at(n->attrs, i)); +} + static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_intrin_t in, spl_ast_node_ref_vec_t *args) { switch (in) { @@ -59,12 +79,37 @@ static spl_ir_node_ref_t ast2ir_intrin_call(spl_ast2ir_t *a, spl_ast_node_t *n, spl_ir_node_ref_t br = spl_ir_builder_control_br(a->ir, notc); spl_ir_builder_block_end(a->ir); - usize trap_blk = spl_ir_builder_block_begin(a->ir); + usize panic_blk = spl_ir_builder_block_begin(a->ir); + + 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)); + if (mn && mn->kind == SPL_AST_EXPR_STRING_LIT && mn->string_lit.data) + user_msg = mn->string_lit.data; + } + + char *msg; + int need; + if (user_msg) { + need = snprintf(NULL, 0, "%s:%d:%d: assert failed: %s", fname, n->dbg.line, n->dbg.col, + user_msg); + msg = malloc((usize)need + 1); + snprintf(msg, (usize)need + 1, "%s:%d:%d: assert failed: %s", fname, n->dbg.line, + n->dbg.col, user_msg); + } else { + need = snprintf(NULL, 0, "%s:%d:%d: assert failed", fname, n->dbg.line, n->dbg.col); + msg = malloc((usize)need + 1); + snprintf(msg, (usize)need + 1, "%s:%d:%d: assert failed", fname, n->dbg.line, + n->dbg.col); + } + + spl_ir_builder_dbg_panic(a->ir, msg, (usize)need); spl_ir_builder_control_trap(a->ir); spl_ir_builder_block_end(a->ir); usize cont_blk = spl_ir_builder_block_begin(a->ir); - spl_ir_builder_control_br_fixup(a->ir, br, trap_blk, cont_blk); + spl_ir_builder_control_br_fixup(a->ir, br, panic_blk, cont_blk); return 0; } case SPL_INTRIN_BREAKPOINT: @@ -259,6 +304,8 @@ static spl_ir_node_ref_t emit_expr(spl_ast2ir_t *a, spl_ast_node_ref_t ref) { if (!n || n->expected_lang_tid == 0) return val; + copy_attrs_to_ir_node(a, n, val); + spl_lang_type_id_t from = n->resolved_lang_tid; spl_lang_type_id_t to = n->expected_lang_tid; if (!from || from == to) @@ -284,8 +331,27 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref) return spl_ir_builder_type_const_float(a->ir, node_ir(a, n), n->float_lit.val); case SPL_AST_EXPR_CHAR_LIT: return spl_ir_builder_type_const_char(a->ir, node_ir(a, n), n->char_lit.val); - case SPL_AST_EXPR_STRING_LIT: - return spl_ir_builder_type_const_cstr(a->ir, node_ir(a, n), n->string_lit.data); + case SPL_AST_EXPR_STRING_LIT: { + 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_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); + spl_type_id_t arr_ir = to_ir_type(a, arr_lang); + + spl_ir_node_ref_t raw = + spl_ir_builder_type_const_bytes(a->ir, arr_ir, n->string_lit.data, n->string_lit.len); + spl_ir_node_ref_t ptr = spl_ir_builder_mem_global_alloc(a->ir, ptr_u8_ir, raw); + spl_ir_node_ref_t len_c = spl_ir_builder_type_const_int(a->ir, usize_ir, len); + + spl_type_id_t slice_ir = node_ir(a, n); + spl_ir_node_ref_t node = spl_ir_builder_agg_construct(a->ir, slice_ir); + spl_ir_builder_agg_construct_field(a->ir, node, ptr); + spl_ir_builder_agg_construct_field(a->ir, node, len_c); + return node; + } case SPL_AST_EXPR_BOOL_LIT: return spl_ir_builder_type_const_bool(a->ir, node_ir(a, n), n->bool_lit.val); case SPL_AST_EXPR_NULL_LIT: @@ -935,10 +1001,11 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) { if (!fn_ir) return; - spl_ir_attr_t attr = {.kind = SPL_IR_ATTR_NONE}; - spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir, attr); + spl_ir_func_ref_t fn_ref = spl_ir_builder_fn_begin(a->ir, n->fn_decl.name, fn_ir); map_put(a->def2ir_map, n->resolved_def_id, (spl_ir_node_ref_t)fn_ref); + copy_attrs_to_ir_func(a, n, fn_ref); + spl_lang_type_id_t saved_ret = a->cur_ret_lang; a->cur_ret_lang = fn_ln->extra.fn.ret; diff --git a/stage1/spl_attr.c b/stage1/spl_attr.c new file mode 100644 index 0000000..7c65acf --- /dev/null +++ b/stage1/spl_attr.c @@ -0,0 +1,152 @@ +#include "spl_attr.h" + +static spl_attr_info_t spl_builtin_attrs[] = { + {NULL, "extern", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_DECL, SPL_ATTR_REQUIRED, 1, 1}, + {NULL, "inline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0}, + {NULL, "noinline", SPL_ATTR_STAGE_OPT, SPL_ATTR_TARGET_DECL, SPL_ATTR_OPTIONAL, 0, 0}, + {NULL, "align", SPL_ATTR_STAGE_LAYOUT, SPL_ATTR_TARGET_TYPE, SPL_ATTR_REQUIRED, 1, 1}, + {NULL, "volatile", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 0}, + {NULL, "atomic", SPL_ATTR_STAGE_IR, SPL_ATTR_TARGET_EXPR, SPL_ATTR_REQUIRED, 0, 1}, +}; + +void spl_attr_init(spl_attr_t *ctx) { + vec_init(ctx->table); + vec_push(ctx->table, (spl_attr_node_t){0}); + vec_init(ctx->registry); + spl_attr_register_builtins(ctx); +} + +void spl_attr_drop(spl_attr_t *ctx) { + for (usize i = 1; i < vec_size(ctx->table); ++i) + vec_free(vec_at(ctx->table, i).args); + vec_free(ctx->table); + vec_free(ctx->registry); +} + +spl_attr_id_t spl_attr_alloc(spl_attr_t *ctx, spl_attr_info_t *info, spl_attr_arg_vec_t args) { + spl_attr_node_t a = {0}; + a.info = info; + a.args = args; + vec_push(ctx->table, a); + return vec_size(ctx->table) - 1; +} + +spl_attr_node_t *spl_attr_node(const spl_attr_t *ctx, spl_attr_id_t id) { + if (!id || id >= vec_size(ctx->table)) + return NULL; + return &vec_at(ctx->table, id); +} + +void spl_attr_registry_add(spl_attr_t *ctx, spl_attr_info_t *info) { + vec_push(ctx->registry, info); +} + +static int name_eq(const char *a, const char *b) { + if (a == NULL && b == NULL) + return 1; + if (a == NULL || b == NULL) + return 0; + return strcmp(a, b) == 0; +} + +spl_attr_info_t *spl_attr_lookup(spl_attr_t *ctx, const char *ns, const char *name) { + for (usize i = 0; i < vec_size(ctx->registry); ++i) { + spl_attr_info_t *info = vec_at(ctx->registry, i); + if (name_eq(info->ns, ns) && strcmp(info->name, name) == 0) + return info; + } + return NULL; +} + +void spl_attr_register_builtins(spl_attr_t *ctx) { + usize n = sizeof(spl_builtin_attrs) / sizeof(spl_builtin_attrs[0]); + for (usize i = 0; i < n; ++i) + spl_attr_registry_add(ctx, &spl_builtin_attrs[i]); +} + +static const char *attr_stage_name(spl_attr_stage_t s) { + switch (s) { + case SPL_ATTR_STAGE_SEMA: + return "SEMA"; + case SPL_ATTR_STAGE_LAYOUT: + return "LAYOUT"; + case SPL_ATTR_STAGE_IR: + return "IR"; + case SPL_ATTR_STAGE_OPT: + return "OPT"; + case SPL_ATTR_STAGE_BACKEND: + return "BACKEND"; + } + return "?"; +} + +static const char *attr_target_name(spl_attr_target_t t) { + switch (t) { + case SPL_ATTR_TARGET_DECL: + return "DECL"; + case SPL_ATTR_TARGET_TYPE: + return "TYPE"; + case SPL_ATTR_TARGET_EXPR: + return "EXPR"; + case SPL_ATTR_TARGET_STMT: + return "STMT"; + } + return "?"; +} + +static const char *attr_demand_name(spl_attr_demand_t d) { + return d == SPL_ATTR_REQUIRED ? "REQUIRED" : "OPTIONAL"; +} + +void spl_attr_dump_id(const spl_attr_t *ctx, spl_attr_id_t id) { + if (!ctx || !id) { + printf("?"); + return; + } + spl_attr_node_t *a = spl_attr_node(ctx, id); + if (!a || !a->info) { + printf("?"); + return; + } + printf("%s", a->info->name); + if (vec_size(a->args) > 0) { + printf("("); + for (usize i = 0; i < vec_size(a->args); ++i) { + if (i > 0) + printf(", "); + spl_attr_arg_t *arg = &vec_at(a->args, i); + switch (arg->kind) { + case SPL_ATTR_ARG_INT: + printf("%zd", arg->value.i); + break; + case SPL_ATTR_ARG_STR: + printf("\"%s\"", arg->value.s ? arg->value.s : ""); + break; + case SPL_ATTR_ARG_DEF: + printf("def#%zu", arg->value.d); + break; + case SPL_ATTR_ARG_TYPE: + printf("type#%zu", arg->value.t); + break; + } + } + printf(")"); + } +} + +void spl_attr_dump(const spl_attr_t *ctx) { + if (!ctx) + return; + printf("AttrTable:\n"); + for (usize i = 1; i < vec_size(ctx->table); ++i) { + spl_attr_node_t *a = &vec_at(ctx->table, i); + printf(" #%zu ", i); + spl_attr_dump_id(ctx, i); + if (a->info) { + printf(" [stage=%s target=%s demand=%s consumed=0x%x]", attr_stage_name(a->info->stage), + attr_target_name(a->info->target), attr_demand_name(a->info->demand), + a->consumed_mask); + } + printf("\n"); + } +} diff --git a/stage1/spl_attr.h b/stage1/spl_attr.h new file mode 100644 index 0000000..b1036bb --- /dev/null +++ b/stage1/spl_attr.h @@ -0,0 +1,84 @@ +#ifndef __SPL_ATTR_H__ +#define __SPL_ATTR_H__ + +#include "../stage0/include/utils.h" + +typedef enum { + SPL_ATTR_STAGE_SEMA, + SPL_ATTR_STAGE_LAYOUT, + SPL_ATTR_STAGE_IR, + SPL_ATTR_STAGE_OPT, + SPL_ATTR_STAGE_BACKEND, +} spl_attr_stage_t; + +typedef enum { + SPL_ATTR_TARGET_DECL, + SPL_ATTR_TARGET_TYPE, + SPL_ATTR_TARGET_EXPR, + SPL_ATTR_TARGET_STMT, +} spl_attr_target_t; + +typedef enum { + SPL_ATTR_OPTIONAL, + SPL_ATTR_REQUIRED, +} spl_attr_demand_t; + +typedef struct { + const char *ns; + const char *name; + spl_attr_stage_t stage; + spl_attr_target_t target; + spl_attr_demand_t demand; + int min_args; + int max_args; +} spl_attr_info_t; + +typedef enum { + SPL_ATTR_ARG_INT, + SPL_ATTR_ARG_STR, + SPL_ATTR_ARG_DEF, + SPL_ATTR_ARG_TYPE, +} spl_attr_arg_kind_t; + +typedef struct { + spl_attr_arg_kind_t kind; + union { + isize i; + const char *s; + usize d; + usize t; + } value; +} spl_attr_arg_t; +typedef VEC(spl_attr_arg_t) spl_attr_arg_vec_t; + +typedef usize spl_attr_id_t; + +typedef struct { + spl_attr_info_t *info; + spl_attr_arg_vec_t args; + uint32_t consumed_mask; +} spl_attr_node_t; +typedef VEC(spl_attr_node_t) spl_attr_node_vec_t; +typedef VEC(spl_attr_id_t) spl_attr_id_vec_t; + +typedef VEC(spl_attr_info_t *) spl_attr_registry_t; + +typedef struct { + spl_attr_node_vec_t table; + spl_attr_registry_t registry; +} spl_attr_t; + +void spl_attr_init(spl_attr_t *ctx); +void spl_attr_drop(spl_attr_t *ctx); + +spl_attr_id_t spl_attr_alloc(spl_attr_t *ctx, spl_attr_info_t *info, spl_attr_arg_vec_t args); +spl_attr_node_t *spl_attr_node(const spl_attr_t *ctx, spl_attr_id_t id); + +void spl_attr_registry_add(spl_attr_t *ctx, spl_attr_info_t *info); +spl_attr_info_t *spl_attr_lookup(spl_attr_t *ctx, const char *ns, const char *name); +void spl_attr_register_builtins(spl_attr_t *ctx); + +void spl_attr_dump(const spl_attr_t *ctx); +void spl_attr_dump_id(const spl_attr_t *ctx, spl_attr_id_t id); + +#endif /* __SPL_ATTR_H__ */ diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index bf66de6..95f95f7 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -28,6 +28,9 @@ static void node_drop_vecs(spl_ir_node_t *n) { case SPL_IR_CONTROL_CALL: vec_free(n->control_call.params); break; + case SPL_IR_DBG_PANIC: + free((char *)n->dbg_panic.msg); + break; default: break; } @@ -36,7 +39,11 @@ static void node_drop_vecs(spl_ir_node_t *n) { void spl_ir_drop(spl_ir_t *ir) { vec_for(ir->funcs, i) { spl_ir_func_t *f = &vec_at(ir->funcs, i); - vec_for(f->nodes, j) { node_drop_vecs(&vec_at(f->nodes, j)); } + vec_for(f->nodes, j) { + vec_free(vec_at(f->nodes, j).attrs); + node_drop_vecs(&vec_at(f->nodes, j)); + } + vec_free(f->attrs); vec_free(f->nodes); } vec_free(ir->funcs); @@ -267,10 +274,25 @@ static void ir_dump_node(const spl_type_t *ty, spl_ir_node_t *n) { case SPL_IR_CONTROL_TRAP: case SPL_IR_DBG_BREAKPOINT: break; + case SPL_IR_DBG_PANIC: + printf(" \"%.*s\"", (int)n->dbg_panic.len, n->dbg_panic.msg); + break; } } -void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { +static void ir_dump_attr_list(const spl_attr_t *attr, spl_attr_id_vec_t *ids) { + if (!attr || !ids || vec_size(*ids) == 0) + return; + printf(" attrs=["); + for (usize i = 0; i < vec_size(*ids); ++i) { + if (i > 0) + printf(", "); + spl_attr_dump_id(attr, vec_at(*ids, i)); + } + printf("]"); +} + +void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty, const spl_attr_t *attr) { vec_for(ir->funcs, i) { if (i == 0) continue; @@ -278,7 +300,9 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { printf("func %s %%%zu", func->name ? func->name : "?", i); printf(" tid = "); spl_type_pure_dump((spl_type_t *)ty, func->fn_tid); + ir_dump_attr_list(attr, &func->attrs); printf("\n"); + vec_for(func->nodes, j) { if (j == 0) continue; @@ -286,10 +310,9 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { printf(" #%zu ", j); printf("%s", spl_ir_kind_name(node->kind)); ir_dump_node(ty, node); + ir_dump_attr_list(attr, &node->attrs); printf("\n"); } - if (vec_size(func->nodes) == 0) - printf(" (extern)\n"); } // if (vec_size(ir->gdata) > 1) { // printf("gdata:\n"); @@ -315,6 +338,7 @@ static spl_ir_node_ref_t builder_alloc_node(spl_ir_builder_t *b, spl_ir_kind_t k spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); n->kind = kind; n->dbg = b->dbg; + vec_init(n->attrs); if (b->current_block >= vec_size(b->blocks)) { Panic("unknown bblock"); @@ -345,14 +369,14 @@ void spl_ir_builder_drop(spl_ir_builder_t *b) { } spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name, - spl_type_id_t fn_tid, spl_ir_attr_t attr) { + spl_type_id_t fn_tid) { if (b->current_fn) { spl_ir_builder_fn_end(b); } spl_ir_func_ref_t fid = spl_ir_alloc_fn(&b->ir); spl_ir_func_t *f = spl_ir_func(&b->ir, fid); f->name = name; - f->attr = attr; + vec_init(f->attrs); f->fn_tid = fn_tid; b->current_fn = fid; @@ -587,13 +611,13 @@ spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_ return ref; } -spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, - const char *val) { +spl_ir_node_ref_t spl_ir_builder_type_const_bytes(spl_ir_builder_t *b, spl_type_id_t tid, + const void *data, usize len) { + (void)len; spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_TYPE_CONST); spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); n->type_const.tid = tid; - TODO(); - // n->type_const.cstr_lit = val; + n->type_const.ptr_lit = (void *)data; return ref; } @@ -792,3 +816,11 @@ spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b) { spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b) { return builder_alloc_node(b, SPL_IR_DBG_BREAKPOINT); } + +spl_ir_node_ref_t spl_ir_builder_dbg_panic(spl_ir_builder_t *b, const char *msg, usize len) { + spl_ir_node_ref_t ref = builder_alloc_node(b, SPL_IR_DBG_PANIC); + spl_ir_node_t *n = spl_ir_node(&b->ir, b->current_fn, ref); + n->dbg_panic.msg = msg; + n->dbg_panic.len = len; + return ref; +} diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index 79c6ae7..e052c3e 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -5,6 +5,8 @@ #include "spl_dbg.h" #include "spl_type.h" +#include "spl_attr.h" + /* clang-format off */ #define SPL_IR_FN_TABLE \ X(arith.add, V0, SPL_IR_ARITH_ADD) \ @@ -63,6 +65,7 @@ X(control.unreachable, V0, SPL_IR_CONTROL_UNREACHABLE) \ X(control.trap, V0, SPL_IR_CONTROL_TRAP) \ X(dbg.breakpoint, V0, SPL_IR_DBG_BREAKPOINT) \ + X(dbg.panic, V0, SPL_IR_DBG_PANIC) \ typedef enum { #ifdef X @@ -82,6 +85,7 @@ typedef usize spl_ir_func_ref_t; /* 0 is error */ typedef struct { spl_ir_kind_t kind; spl_dbg_node_t dbg; + spl_attr_id_vec_t attrs; union { spl_type_id_t tid; struct { @@ -211,26 +215,18 @@ typedef struct { spl_type_id_t tid; spl_ir_node_ref_t val; } control_ret; + + struct { + const char *msg; + usize len; + } dbg_panic; }; } spl_ir_node_t; typedef VEC(spl_ir_node_t) spl_ir_node_vec_t; -typedef struct { - enum { - SPL_IR_ATTR_NONE, - SPL_IR_ATTR_LINK, /* 不实现 */ - SPL_IR_ATTR_ABI, /* 只有 C ABI 支持 */ - SPL_IR_ATTR_SYMBOL, /* 不实现 */ - SPL_IR_ATTR_NAKED, /* 不实现 */ - SPL_IR_ATTR_NOINLINE, /* 不实现 */ - SPL_IR_ATTR_ALWAYSINLINE, /* 不实现 */ - } kind; -} spl_ir_attr_t; -typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t; - typedef struct { const char *name; - spl_ir_attr_t attr; + spl_attr_id_vec_t attrs; spl_type_id_t fn_tid; spl_ir_node_vec_t nodes; } spl_ir_func_t; @@ -259,7 +255,7 @@ spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir); spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_ref_t node_id); spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id); -void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty); +void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty, const spl_attr_t *attr); const char *spl_ir_kind_name(spl_ir_kind_t kind); typedef struct { @@ -312,7 +308,7 @@ void spl_ir_builder_init(spl_ir_builder_t *b); void spl_ir_builder_drop(spl_ir_builder_t *b); spl_ir_func_ref_t spl_ir_builder_fn_begin(spl_ir_builder_t *b, const char *name, - spl_type_id_t fn_tid, spl_ir_attr_t attr); + spl_type_id_t fn_tid); void spl_ir_builder_fn_end(spl_ir_builder_t *b); usize spl_ir_builder_block_begin(spl_ir_builder_t *b); @@ -370,8 +366,8 @@ spl_ir_node_ref_t spl_ir_builder_type_const_bool(spl_ir_builder_t *b, spl_type_i spl_ir_node_ref_t spl_ir_builder_type_const_int(spl_ir_builder_t *b, spl_type_id_t tid, usize val); spl_ir_node_ref_t spl_ir_builder_type_const_float(spl_ir_builder_t *b, spl_type_id_t tid, double val); -spl_ir_node_ref_t spl_ir_builder_type_const_cstr(spl_ir_builder_t *b, spl_type_id_t tid, - const char *val); +spl_ir_node_ref_t spl_ir_builder_type_const_bytes(spl_ir_builder_t *b, spl_type_id_t tid, + const void *data, usize len); spl_ir_node_ref_t spl_ir_builder_type_const_char(spl_ir_builder_t *b, spl_type_id_t tid, char val); spl_ir_node_ref_t spl_ir_builder_type_const_fn(spl_ir_builder_t *b, spl_type_id_t tid, spl_ir_func_ref_t val); @@ -419,5 +415,6 @@ spl_ir_node_ref_t spl_ir_builder_control_unreachable(spl_ir_builder_t *b); spl_ir_node_ref_t spl_ir_builder_control_trap(spl_ir_builder_t *b); spl_ir_node_ref_t spl_ir_builder_dbg_breakpoint(spl_ir_builder_t *b); +spl_ir_node_ref_t spl_ir_builder_dbg_panic(spl_ir_builder_t *b, const char *msg, usize len); #endif /* __SPL_IR_H__ */ diff --git a/stage1/spl_ir2vm.c b/stage1/spl_ir2vm.c index e56efb0..4c02854 100644 --- a/stage1/spl_ir2vm.c +++ b/stage1/spl_ir2vm.c @@ -68,6 +68,41 @@ static usize ir_agg_field_off(spl_ir2vm_t *ctx, spl_type_id_t tid, usize idx) { return 0; } +static int get_or_add_native(spl_ir2vm_t *ctx, const char *name) { + if (!name) + return -1; + for (usize i = 0; i < vec_size(ctx->prog.natives); ++i) { + spl_vm_native_t *n = &vec_at(ctx->prog.natives, i); + if (n->name && strcmp(n->name, name) == 0) + return (int)i; + } + spl_vm_native_t nat = {0}; + nat.name = strdup(name); + nat.idx_of_strtab = 0; + nat.impl_fn = NULL; + vec_push(ctx->prog.natives, nat); + return (int)(vec_size(ctx->prog.natives) - 1); +} + +static bool fn_check_extern(spl_ir2vm_t *ctx, spl_ir_func_t *f, const char **out_target) { + if (out_target) + *out_target = NULL; + if (!ctx->attr || !f) + return false; + for (usize i = 0; i < vec_size(f->attrs); ++i) { + spl_attr_node_t *a = spl_attr_node(ctx->attr, vec_at(f->attrs, i)); + if (!a || !a->info) + continue; + if (strcmp(a->info->name, "extern") != 0) + continue; + a->consumed_mask |= (1u << SPL_ATTR_STAGE_IR); + if (out_target && vec_size(a->args) >= 1 && vec_at(a->args, 0).kind == SPL_ATTR_ARG_STR) + *out_target = vec_at(a->args, 0).value.s; + return true; + } + return false; +} + static uint8_t vm_kind_of(spl_ir2vm_t *ctx, spl_type_id_t tid) { spl_type_node_t *tn = spl_type_node(ctx->type, tid); if (!tn) @@ -217,17 +252,12 @@ static usize node_data_size(spl_ir2vm_t *ctx, const spl_ir_func_t *f, const spl_ if (ir_is_aggregate(ctx, node->mem_load.tid)) return ir_type_size(ctx, node->mem_load.tid); return 0; + case SPL_IR_DBG_PANIC: + return sizeof(spl_vm_val_t) * 4; /* TODO: fmt slice + msg slice */ case SPL_IR_CONTROL_CALL: if (ir_is_aggregate(ctx, node->control_call.tid)) return ir_type_size(ctx, node->control_call.tid); return 0; - case SPL_IR_TYPE_CONST: { - spl_type_node_t *tn = spl_type_node(ctx->type, node->type_const.tid); - if (tn && (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY || - tn->kind == SPL_TYPE_UNION)) - return ir_type_size(ctx, node->type_const.tid); - return 0; - } default: return 0; } @@ -415,30 +445,17 @@ static void cg_const(cgen_t *cg, usize ref, const spl_ir_node_t *n) { return; if (tn->kind == SPL_TYPE_FN) { - usize idx = ip_of(cg); - CG_PUSH(cg, SPL_PTR, 0); - cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn); - cg_store_slot(cg, ref, SPL_PTR); - return; - } + isize nat_idx = -1; + if (n->type_const.fn > 0) + map_get(ctx->extern_native, n->type_const.fn, &nat_idx); - if (tn->kind == SPL_TYPE_STRUCT || tn->kind == SPL_TYPE_ARRAY || tn->kind == SPL_TYPE_UNION) { - const char *bytes = (const char *)n->type_const.ptr_lit; - if (!bytes) - bytes = ""; - usize len = strlen(bytes); - usize data_idx = (usize)spl_prog_add_data(&ctx->prog, (void *)bytes, len + 1); - usize base = vec_at(cg->frame.slots, ref).data_off; - usize ptr_off = ir_agg_field_off(ctx, tid, 0); - usize len_off = ir_agg_field_off(ctx, tid, 1); - - CG_GADDR(cg, data_idx); - cg_store_at(cg, base + ptr_off, SPL_PTR); - - CG_PUSH(cg, SPL_U64, len); - cg_store_at(cg, base + len_off, SPL_U64); - - CG_LADDR(cg, base); + if (nat_idx >= 0) { + CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx); + } else { + usize idx = ip_of(cg); + CG_PUSH(cg, SPL_PTR, 0); + cg_add_fix(cg, idx, FIX_FNADDR, 0, n->type_const.fn); + } cg_store_slot(cg, ref, SPL_PTR); return; } @@ -506,6 +523,21 @@ static void cg_mem(cgen_t *cg, usize ref, const spl_ir_node_t *n) { break; } + case SPL_IR_MEM_GLOBAL_ALLOC: { + const spl_ir_node_t *cn = &vec_at(cg->irf->nodes, n->mem_global_alloc.const_node); + int idx = 0; + if (cn->kind == SPL_IR_TYPE_CONST && cn->type_const.ptr_lit) { + usize size = ir_type_size(ctx, cn->type_const.tid); + idx = spl_prog_add_data(&ctx->prog, cn->type_const.ptr_lit, size); + } + if (idx > 0) + emit(cg, SPL_GADDR, SPL_VOID, (spl_vm_val_t)idx); + else + CG_PUSH(cg, SPL_PTR, 0); + cg_store_slot(cg, ref, SPL_PTR); + break; + } + case SPL_IR_MEM_LOAD: { spl_type_id_t tid = n->mem_load.tid; if (ir_is_aggregate(ctx, tid)) { @@ -716,43 +748,48 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) { } case SPL_IR_CONTROL_CALL: { - usize nargs = vec_size(n->control_call.params); - for (usize i = 0; i < nargs; ++i) { - spl_ir_node_ref_t pref = vec_at(n->control_call.params, i); - const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref); - spl_type_id_t ptid = ir_result_tid(pn); - uint8_t pk = vm_kind_of(ctx, ptid); - cg_load_slot(cg, pref, pk); - } - - bool direct = false; + spl_ir_func_ref_t callee_ref = 0; spl_ir_node_ref_t fref = n->control_call.func; if (fref < vec_size(cg->irf->nodes)) { const spl_ir_node_t *fn_node = &vec_at(cg->irf->nodes, fref); - if (fn_node->kind == SPL_IR_TYPE_CONST) { - spl_type_node_t *ftn = spl_type_node(ctx->type, fn_node->type_const.tid); - if (ftn && ftn->kind == SPL_TYPE_FN) { - usize idx = ip_of(cg); - CG_PUSH(cg, SPL_PTR, 0); - cg_add_fix(cg, idx, FIX_FNADDR, 0, fn_node->type_const.fn); - emit(cg, SPL_CALL, SPL_VOID, nargs); - direct = true; - } - } + if (fn_node->kind == SPL_IR_TYPE_CONST) + callee_ref = fn_node->type_const.fn; } - if (!direct) - emit(cg, SPL_HALT, SPL_VOID, 0); - spl_type_id_t rtid = n->control_call.tid; - if (ir_is_aggregate(ctx, rtid)) { - cg_store_slot(cg, ref, SPL_PTR); - usize data = vec_at(cg->frame.slots, ref).data_off; - cg_copy_agg(cg, ptr_slot(vec_at(cg->frame.slots, ref).result_off), direct_data(data), - rtid); - CG_LADDR(cg, data); - cg_store_slot(cg, ref, SPL_PTR); + isize nat_idx = -1; + if (callee_ref > 0) + map_get(ctx->extern_native, callee_ref, &nat_idx); + + usize nargs = vec_size(n->control_call.params); + + if (nat_idx >= 0) { + for (usize i = 0; i < nargs; ++i) { + spl_ir_node_ref_t pref = vec_at(n->control_call.params, i); + const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref); + spl_type_id_t ptid = ir_result_tid(pn); + uint8_t pk = vm_kind_of(ctx, ptid); + cg_load_slot(cg, pref, pk); + } + CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat_idx); + emit(cg, SPL_NCALL, SPL_VOID, (spl_vm_val_t)nargs); + + uint8_t rk = vm_kind_of(ctx, n->control_call.tid); + if (rk == SPL_VOID) + emit(cg, SPL_DROP, SPL_VOID, 0); /* NCALL 总是 push 一个结果 */ + else + cg_store_slot(cg, ref, rk); } else { - uint8_t rk = vm_kind_of(ctx, rtid); + for (usize i = 0; i < nargs; ++i) { + spl_ir_node_ref_t pref = vec_at(n->control_call.params, i); + const spl_ir_node_t *pn = &vec_at(cg->irf->nodes, pref); + spl_type_id_t ptid = ir_result_tid(pn); + uint8_t pk = vm_kind_of(ctx, ptid); + cg_load_slot(cg, pref, pk); + } + cg_load_slot(cg, fref, SPL_PTR); + emit(cg, SPL_CALL, SPL_VOID, (spl_vm_val_t)nargs); + + uint8_t rk = vm_kind_of(ctx, n->control_call.tid); if (rk != SPL_VOID) cg_store_slot(cg, ref, rk); } @@ -761,7 +798,7 @@ static void cg_control(cgen_t *cg, usize ref, const spl_ir_node_t *n) { case SPL_IR_CONTROL_UNREACHABLE: case SPL_IR_CONTROL_TRAP: - emit(cg, SPL_HALT, SPL_VOID, 0); + emit(cg, SPL_HALT, SPL_VOID, 1); break; default: @@ -817,9 +854,18 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) { case SPL_IR_ARITH_NEG: cg_unop(cg, ref, n, SPL_NEG); break; - case SPL_IR_ARITH_NOT: - cg_unop(cg, ref, n, SPL_NOT); + case SPL_IR_ARITH_NOT: { + spl_type_node_t *tn = spl_type_node(cg->ctx->type, n->arith.tid); + if (tn && tn->kind == SPL_TYPE_BOOL) { + cg_load_slot(cg, n->arith.left, SPL_BOOL); + CG_PUSH(cg, SPL_U8, 0); + CG_OP(cg, SPL_EQ, SPL_U8); + cg_store_slot(cg, ref, SPL_BOOL); + } else { + cg_unop(cg, ref, n, SPL_NOT); + } break; + } case SPL_IR_ARITH_ABS: break; @@ -869,6 +915,7 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) { break; case SPL_IR_MEM_ALLOCA: + case SPL_IR_MEM_GLOBAL_ALLOC: case SPL_IR_MEM_LOAD: case SPL_IR_MEM_STORE: case SPL_IR_MEM_OFFSET: @@ -898,6 +945,39 @@ static void cg_node(cgen_t *cg, usize ref, const spl_ir_node_t *n) { cg_control(cg, ref, n); break; + case SPL_IR_DBG_PANIC: { + spl_ir2vm_t *ctx = cg->ctx; + usize data = vec_at(cg->frame.slots, ref).data_off; + + int msg_idx = spl_prog_add_data(&ctx->prog, (void *)n->dbg_panic.msg, n->dbg_panic.len); + int fmt_idx = spl_prog_add_data(&ctx->prog, "%s", 2); + if (msg_idx <= 0 || fmt_idx <= 0) + break; + + /* fmt slice = {ptr, len=2} 写到 data+0 */ + CG_GADDR(cg, (spl_vm_val_t)fmt_idx); + cg_store_at(cg, data + 0, SPL_PTR); + CG_PUSH(cg, SPL_U64, 2); + cg_store_at(cg, data + 8, SPL_U64); + + /* msg slice = {ptr, len} 写到 data+16 */ + CG_GADDR(cg, (spl_vm_val_t)msg_idx); + cg_store_at(cg, data + 16, SPL_PTR); + CG_PUSH(cg, SPL_U64, n->dbg_panic.len); + cg_store_at(cg, data + 24, SPL_U64); + + /* push fmt slice 指针,push msg slice 指针 */ + CG_LADDR(cg, data + 0); + CG_LADDR(cg, data + 16); + + /* NCALL vm_printf(2) */ + int nat = get_or_add_native(ctx, "vm_printf"); + CG_PUSH(cg, SPL_U64, (spl_vm_val_t)nat); + emit(cg, SPL_NCALL, SPL_VOID, 2); + emit(cg, SPL_DROP, SPL_VOID, 0); /* 丢弃返回值 */ + break; + } + case SPL_IR_DBG_BREAKPOINT: emit(cg, SPL_BK, SPL_VOID, 0); break; @@ -963,13 +1043,23 @@ static usize translate_function(spl_ir2vm_t *ctx, spl_ir_func_ref_t fid, fix_vec return func_ip; } -void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type) { +static usize spl_map_hash(usize k) { return MAP_HASH_INT(k); } +static int spl_map_cmp(usize a, usize b) { return MAP_CMP_INT(a, b); } + +void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type, + const spl_attr_t *attr) { + Assert(ir != NULL && type != NULL && attr != NULL); ctx->ir = ir; ctx->type = type; + ctx->attr = attr; + map_init(ctx->extern_native, spl_map_hash, spl_map_cmp); spl_prog_init(&ctx->prog); } -void spl_ir2vm_drop(spl_ir2vm_t *ctx) { spl_prog_drop(&ctx->prog); } +void spl_ir2vm_drop(spl_ir2vm_t *ctx) { + spl_prog_drop(&ctx->prog); + map_free(ctx->extern_native); +} int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref) { fix_vec_t all_fixups; @@ -984,13 +1074,30 @@ int spl_ir2vm_run(spl_ir2vm_t *ctx) { if (n <= 1) return 0; + /* Pass 1:扫描所有 fn,把 extern 的登记到 map 里 */ + for (spl_ir_func_ref_t i = 1; i < n; ++i) { + spl_ir_func_t *irf = spl_ir_func((spl_ir_t *)ctx->ir, i); + if (!irf) + continue; + if (fn_check_extern(ctx, irf, NULL)) { + int nat_idx = get_or_add_native(ctx, irf->name); + map_put(ctx->extern_native, i, (isize)nat_idx); + } + } + + /* Pass 2:翻译非 extern 的函数 */ usize *fid_ip = calloc(n, sizeof(usize)); fix_vec_t all_fixups; vec_init(all_fixups); - for (spl_ir_func_ref_t i = 1; i < n; ++i) + for (spl_ir_func_ref_t i = 1; i < n; ++i) { + isize dummy = -1; + if (map_get(ctx->extern_native, i, &dummy)) + continue; fid_ip[i] = translate_function(ctx, i, &all_fixups); + } + /* FNADDR 回填 */ for (usize i = 0; i < vec_size(all_fixups); ++i) { fix_t *fx = &vec_at(all_fixups, i); if (fx->kind != FIX_FNADDR) diff --git a/stage1/spl_ir2vm.h b/stage1/spl_ir2vm.h index 012f1a0..a3b21dc 100644 --- a/stage1/spl_ir2vm.h +++ b/stage1/spl_ir2vm.h @@ -12,16 +12,20 @@ typedef struct { } spl_ir2vm_fdbg_t; typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t; +typedef MAP(spl_ir_func_ref_t, isize) spl_extern_idx_map_t; // MAP() typedef struct { const spl_ir_t *ir; const spl_type_t *type; + const spl_attr_t *attr; + spl_extern_idx_map_t extern_native; spl_prog_t prog; // spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */ } spl_ir2vm_t; -void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type); +void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type, + const spl_attr_t *attr); void spl_ir2vm_drop(spl_ir2vm_t *ctx); int spl_ir2vm_run_func(spl_ir2vm_t *ctx, spl_ir_func_ref_t ref); diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index bf7e977..dc0d29b 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -53,6 +53,92 @@ bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { 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: + return &n->fn_decl.tag_list; + case SPL_AST_VAR_DECL: + case SPL_AST_CONST_DECL: + return &n->var_const_decl.attr_list; + case SPL_AST_TYPE_DECL: + return &n->type_decl.attr_list; + case SPL_AST_PARAM_DECL: + return &n->param_decl.attr_list; + case SPL_AST_MEMBER_DECL: + return &n->member_decl.attr_list; + case SPL_AST_TOP_LEVEL_BLOCK: + return &n->top_level_block.tag_list; + default: + return NULL; + } +} + +static void sema_resolve_attrs(spl_sema_t *sema, spl_ast_node_ref_vec_t *raw, + spl_attr_id_vec_t *out) { + for (usize i = 0; i < vec_size(*raw); ++i) { + spl_ast_node_ref_t aref = vec_at(*raw, i); + spl_ast_node_t *a = spl_ast_node(sema->ast, aref); + if (!a || (a->kind != SPL_AST_TAG_ITEM && a->kind != SPL_AST_EXTERNAL_TAG_ITEM)) + continue; + + spl_attr_info_t *info = spl_attr_lookup(sema->attr, NULL, a->tag_item.name); + if (!info) { + SPL_ERROR(&a->dbg, "unknown attribute `%s`", a->tag_item.name); + sema->error_count++; + continue; + } + + usize nargs = vec_size(a->tag_item.args); + if ((int)nargs < info->min_args || (info->max_args >= 0 && (int)nargs > info->max_args)) { + SPL_ERROR(&a->dbg, "attribute `%s` expects %d..%d args, got %zu", info->name, + info->min_args, info->max_args, nargs); + sema->error_count++; + continue; + } + + spl_attr_arg_vec_t args; + vec_init(args); + int bad = 0; + for (usize j = 0; j < nargs; ++j) { + spl_ast_node_t *arg = spl_ast_node(sema->ast, vec_at(a->tag_item.args, j)); + spl_attr_arg_t oa = {0}; + if (!arg) { + bad = 1; + break; + } + switch (arg->kind) { + case SPL_AST_EXPR_IDENT: + oa.kind = SPL_ATTR_ARG_STR; + oa.value.s = arg->ident.name; + break; + case SPL_AST_EXPR_STRING_LIT: + oa.kind = SPL_ATTR_ARG_STR; + oa.value.s = arg->string_lit.data; + break; + case SPL_AST_EXPR_INT_LIT: + oa.kind = SPL_ATTR_ARG_INT; + oa.value.i = arg->int_lit.val; + break; + default: + SPL_ERROR(&a->dbg, "attribute arg #%zu has unsupported form", j); + sema->error_count++; + bad = 1; + break; + } + if (bad) + break; + vec_push(args, oa); + } + if (bad) { + vec_free(args); + continue; + } + + spl_attr_id_t id = spl_attr_alloc(sema->attr, info, args); + vec_push(*out, id); + } +} + static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref); static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref); static spl_lang_type_id_t sema_check(spl_sema_t *sema, spl_ast_node_ref_t ref, @@ -90,11 +176,6 @@ static bool sema_is_literal(spl_ast_node_t *n) { } } -static bool sema_is_numeric(spl_sema_t *sema, spl_lang_type_id_t tid) { - spl_lang_type_node_t *n = spl_lang_type_node(sema->type, tid); - return n && (n->kind == SPL_LANG_TYPE_INT || n->kind == SPL_LANG_TYPE_FLOAT); -} - static inline void sema_push_scope(spl_sema_t *sema) { spl_scope_id_t new_scope = spl_scope_alloc(sema->scope); sema->store_scope = sema->scope->current_scope; @@ -213,8 +294,6 @@ static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } -static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref); - static spl_lang_type_id_t sema_intrin_call(spl_sema_t *sema, spl_ast_node_t *n, spl_intrin_t in, spl_ast_node_ref_vec_t *args) { const spl_intrin_info_t *info = spl_intrin_info(in); @@ -507,6 +586,10 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { if (!n) return 0; + spl_ast_node_ref_vec_t *raw = node_attr_list(n); + if (raw && vec_size(*raw) > 0) + sema_resolve_attrs(sema, raw, &n->attrs); + switch (n->kind) { /* ---------- 字面量 ---------- */ @@ -1038,13 +1121,14 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } /* ---------- IFVAR / WHILE / LOOP / FOR / MATCH ---------- */ - case SPL_AST_EXPR_IFVAR: + case SPL_AST_EXPR_IFVAR: { sema_infer(sema, n->ifvar_expr.var_decl); if (n->ifvar_expr.then_block) sema_infer(sema, n->ifvar_expr.then_block); if (n->ifvar_expr.else_branch) sema_infer(sema, n->ifvar_expr.else_branch); return 0; + } case SPL_AST_EXPR_WHILE: { spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); sema_check(sema, n->while_expr.cond, bt); @@ -1054,10 +1138,11 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema_infer(sema, n->while_expr.else_branch); return 0; } - case SPL_AST_EXPR_LOOP: + case SPL_AST_EXPR_LOOP: { if (n->loop_expr.body) sema_infer(sema, n->loop_expr.body); return 0; + } case SPL_AST_EXPR_FOR: { sema_push_scope(sema); for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) { @@ -1086,7 +1171,7 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema_pop_scope(sema); return 0; } - case SPL_AST_EXPR_MATCH: + case SPL_AST_EXPR_MATCH: { sema_infer(sema, n->match_expr.matched_expr); for (usize i = 0; i < vec_size(n->match_expr.arms); ++i) { spl_ast_node_t *arm = spl_ast_node(sema->ast, vec_at(n->match_expr.arms, i)); @@ -1096,6 +1181,7 @@ 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: { @@ -1356,14 +1442,16 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { } /* ---------- MEMBER / PARAM ---------- */ - case SPL_AST_MEMBER_DECL: + case SPL_AST_MEMBER_DECL: { if (n->member_decl.type_expr) return sema_infer(sema, n->member_decl.type_expr); return 0; - case SPL_AST_PARAM_DECL: + } + case SPL_AST_PARAM_DECL: { if (n->param_decl.type_expr) return sema_infer(sema, n->param_decl.type_expr); return 0; + } /* ---------- 语句 ---------- */ case SPL_AST_STATEMENT_RET: { @@ -1412,1142 +1500,15 @@ static spl_lang_type_id_t sema_infer(spl_sema_t *sema, spl_ast_node_ref_t ref) { return 0; } -static spl_lang_type_id_t sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { - if (ref == 0) - return 0; - spl_ast_node_t *n = spl_ast_node(sema->ast, ref); - if (!n) - return 0; - - switch (n->kind) { - case SPL_AST_CONTAINER_MEMBERS: - for (usize i = 0; i < vec_size(n->container_members.declarations); ++i) { - sema_parse(sema, vec_at(n->container_members.declarations, i)); - } - return 0; - - case SPL_AST_FN_DECL: { - if (n->resolved_def_id == 0) { - Panic("fn `%s` not collected", n->fn_decl.name); - } - - spl_lang_type_id_vec_t param_types; - vec_init(param_types); - for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { - spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i)); - if (pd && pd->kind == SPL_AST_PARAM_DECL && pd->param_decl.type_expr) { - vec_push(param_types, sema_parse(sema, pd->param_decl.type_expr)); - } else { - vec_push(param_types, spl_lang_make_varargs(sema->type)); - } - } - spl_lang_type_id_t ret_tid = sema_parse(sema, n->fn_decl.ret_type); - if (ret_tid == 0) { - ret_tid = spl_lang_make_unit(sema->type); - } - spl_lang_type_id_t fn_tid = spl_lang_make_fn( - sema->type, ret_tid, vec_unsafe_get_data(param_types), vec_size(param_types)); - Assert(fn_tid != 0); - vec_free(param_types); - spl_def_resolve(sema->type, n->resolved_def_id, fn_tid); - - if (n->fn_decl.body) { - sema_push_scope(sema); - for (usize i = 0; i < vec_size(n->fn_decl.params); ++i) { - spl_ast_node_t *pd = spl_ast_node(sema->ast, vec_at(n->fn_decl.params, i)); - if (pd && pd->kind == SPL_AST_PARAM_DECL) { - spl_symbol_t psym = {.name = pd->param_decl.name, .kind = SPL_SYMBOL_KIND_VAR}; - psym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, psym.name, pd->dbg, - vec_at(n->fn_decl.params, i)); - spl_lang_type_id_t p_tid = sema_parse(sema, pd->param_decl.type_expr); - spl_def_resolve(sema->type, psym.node, p_tid); - pd->resolved_def_id = psym.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, psym); - } - } - spl_lang_type_id_t old_ret = sema->current_fn_ret_tid; - sema->current_fn_ret_tid = ret_tid; - sema_parse(sema, n->fn_decl.body); - sema->current_fn_ret_tid = old_ret; - sema_pop_scope(sema); - } - return fn_tid; - } - - case SPL_AST_TYPE_DECL: { - if (!n->type_decl.type_expr) - break; - spl_ast_node_t *te = spl_ast_node(sema->ast, n->type_decl.type_expr); - if (!te) - break; - - if (te->kind == SPL_AST_TYPE_AGGREGATE) { - spl_type_member_vec_t members; - vec_init(members); - for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { - spl_ast_node_t *mn = spl_ast_node(sema->ast, vec_at(te->type_aggregate.members, i)); - if (mn && mn->kind == SPL_AST_MEMBER_DECL) { - spl_lang_type_id_t mtid = sema_parse(sema, mn->member_decl.type_expr); - spl_type_member_t m = {.name = mn->member_decl.name, - .type_id = spl_lang_type_get_ir_type(sema->type, mtid), - .ast_node_ref = vec_at(te->type_aggregate.members, i)}; - vec_push(members, m); - } - } - - spl_type_node_kind_t tk; - if (strcmp(te->type_aggregate.kind_name, "struct") == 0) - tk = SPL_TYPE_STRUCT; - else if (strcmp(te->type_aggregate.kind_name, "union") == 0) - tk = SPL_TYPE_UNION; - else if (strcmp(te->type_aggregate.kind_name, "enum") == 0) - tk = SPL_TYPE_ENUM; - else - tk = SPL_TYPE_STRUCT; - - spl_type_layout_t layout = {.mode = SPL_TYPE_LAYOUT_AUTO}; - spl_type_id_t agg_ir = spl_type_builder_agg( - sema->type, tk, &members, spl_type_builder_int(sema->type, 32, 1), layout); - vec_free(members); - - spl_lang_type_kind_t lk; - switch (tk) { - case SPL_TYPE_STRUCT: - lk = SPL_LANG_TYPE_STRUCT; - break; - case SPL_TYPE_UNION: - lk = SPL_LANG_TYPE_UNION; - break; - case SPL_TYPE_ENUM: - lk = SPL_LANG_TYPE_ENUM; - break; - case SPL_TYPE_SHAPE: - lk = SPL_LANG_TYPE_SHAPE; - break; - default: - lk = SPL_LANG_TYPE_STRUCT; - break; - } - - spl_lang_type_node_t lang_node = {0}; - lang_node.kind = lk; - lang_node.ir_type_id = agg_ir; - spl_lang_type_id_t agg_lang = spl_lang_node_push(sema->type, &lang_node); - spl_def_resolve(sema->type, n->resolved_def_id, agg_lang); - n->resolved_lang_tid = agg_lang; - - /* 聚合内部函数:方法后续单独处理,这里暂只做函数体的语义解析 */ - for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) { - spl_ast_node_t *mn = spl_ast_node(sema->ast, vec_at(te->type_aggregate.members, i)); - if (mn && mn->kind == SPL_AST_FN_DECL) { - sema_parse(sema, vec_at(te->type_aggregate.members, i)); - } - } - } else { - spl_lang_type_id_t tid = sema_parse(sema, n->type_decl.type_expr); - spl_def_resolve(sema->type, n->resolved_def_id, tid); - n->resolved_lang_tid = tid; - } - break; - } - - case SPL_AST_VAR_DECL: - case SPL_AST_CONST_DECL: { - spl_ast_node_t *pat = spl_ast_node(sema->ast, n->var_const_decl.pattern); - if (!pat || pat->kind != SPL_AST_PATTERN_IDENT) { - SPL_ERROR(&n->dbg, "unsupported variable pattern"); - sema->error_count++; - return 0; - } - const char *name = pat->pattern_ident.name; - - if (n->resolved_def_id == 0) { - spl_symbol_t sym = {.name = name, .kind = SPL_SYMBOL_KIND_VAR}; - sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, name, n->dbg, ref); - n->resolved_def_id = sym.node; - spl_scope_insert(sema->scope, sema->scope->current_scope, sym); - } - - spl_lang_type_id_t decl_tid; - if (n->var_const_decl.type) { - decl_tid = sema_parse(sema, n->var_const_decl.type); - } else { - decl_tid = spl_lang_make_infer(sema->type); - } - if (n->var_const_decl.init_expr == 0) { - SPL_ERROR(&n->dbg, "variable `%s` must be initialized", name); - sema->error_count++; - return 0; - } - - spl_ast_node_t *init_node = spl_ast_node(sema->ast, n->var_const_decl.init_expr); - spl_lang_type_id_t init_tid = sema_parse(sema, n->var_const_decl.init_expr); - spl_lang_type_id_t coerce_result = spl_lang_type_coerce_to(sema->type, decl_tid, init_tid); - if (coerce_result == 0) { - SPL_ERROR(&n->dbg, "cannot coerce initializer to declared type"); - sema->error_count++; - return 0; - } - init_node->resolved_lang_tid = coerce_result; - decl_tid = coerce_result; - - spl_def_resolve(sema->type, n->resolved_def_id, decl_tid); - n->resolved_lang_tid = decl_tid; - return decl_tid; - } - - case SPL_AST_MEMBER_DECL: { - if (n->member_decl.type_expr) { - return sema_parse(sema, n->member_decl.type_expr); - } - return 0; - } - - case SPL_AST_PARAM_DECL: { - if (n->param_decl.type_expr) { - return sema_parse(sema, n->param_decl.type_expr); - } - return 0; - } - - case SPL_AST_EXPR_INT_LIT: { - spl_lang_type_id_t ct = spl_lang_make_int(sema->type, 0, 1); - n->resolved_lang_tid = ct; - return ct; - } - case SPL_AST_EXPR_FLOAT_LIT: { - spl_lang_type_id_t ct = spl_lang_make_float(sema->type, 0); - n->resolved_lang_tid = ct; - return ct; - } - case SPL_AST_EXPR_CHAR_LIT: { - spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); - n->resolved_lang_tid = u8; - return u8; - } - case SPL_AST_EXPR_STRING_LIT: { - spl_lang_type_id_t u8 = spl_lang_make_int(sema->type, 8, 0); - spl_lang_type_id_t slice = spl_lang_make_slice(sema->type, u8); - n->resolved_lang_tid = slice; - return slice; - } - case SPL_AST_EXPR_BOOL_LIT: { - spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_lang_tid = bt; - return bt; - } - case SPL_AST_EXPR_NULL_LIT: { - spl_lang_type_id_t never = spl_lang_make_never(sema->type); - spl_lang_type_id_t ptr = spl_lang_make_ptr(sema->type, never); - n->resolved_lang_tid = ptr; - return ptr; - } - case SPL_AST_EXPR_UNDEFINED_LIT: { - spl_lang_type_id_t t = spl_lang_make_never(sema->type); - n->resolved_lang_tid = t; - return t; - } - case SPL_AST_EXPR_IDENT: { - const char *name = n->ident.name; - spl_symbol_t sym; - if (!spl_scope_find(sema->scope, name, &sym)) { - SPL_ERROR(&n->dbg, "undefined identifier `%s`", name); - sema->error_count++; - return 0; - } - if (sym.node == 0) { - SPL_ERROR(&n->dbg, "identifier `%s` has no definition", name); - sema->error_count++; - return 0; - } - n->resolved_def_id = sym.node; - spl_def_node_t *def = spl_def_node(sema->type, sym.node); - if (!def) { - SPL_ERROR(&n->dbg, "definition for `%s` not found", name); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = def->lang_id; - return def->lang_id; - } - - case SPL_AST_EXPR_UNARY: { - spl_lang_type_id_t operand_tid = sema_parse(sema, n->unary.operand); - if (operand_tid == 0) - return 0; - spl_lang_type_node_t *tn = spl_lang_type_node(sema->type, operand_tid); - if (!tn) - return 0; - - switch (n->unary.op) { - case SPL_UNARY_OP_MINUS: - if (tn->kind != SPL_LANG_TYPE_INT && tn->kind != SPL_LANG_TYPE_FLOAT) { - SPL_ERROR(&n->dbg, "unary minus requires numeric operand"); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = operand_tid; - return operand_tid; - case SPL_UNARY_OP_NOT: - if (tn->kind != SPL_LANG_TYPE_BOOL) { - SPL_ERROR(&n->dbg, "logical not requires bool operand"); - sema->error_count++; - return 0; - } - { - spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_lang_tid = bt; - return bt; - } - case SPL_UNARY_OP_BIT_NOT: - if (tn->kind != SPL_LANG_TYPE_INT) { - SPL_ERROR(&n->dbg, "bitwise not requires integer operand"); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = operand_tid; - return operand_tid; - case SPL_UNARY_OP_ADDRESS: { - spl_lang_type_id_t ptr_tid = spl_lang_make_ptr(sema->type, operand_tid); - n->resolved_lang_tid = ptr_tid; - return ptr_tid; - } - default: - UNREACHABLE(); - } - break; - } - - case SPL_AST_EXPR_BINARY: { - spl_lang_type_id_t lt = sema_parse(sema, n->binary.left); - spl_lang_type_id_t rt = sema_parse(sema, n->binary.right); - spl_binary_op_t op = n->binary.op; - - switch (op) { - case SPL_OP_ASSIGN: { - spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt); - if (r == 0) { - SPL_ERROR(&n->dbg, "assignment type mismatch"); - sema->error_count++; - return 0; - } - rhs->resolved_lang_tid = r; - n->resolved_lang_tid = lt; - return lt; - } - - case SPL_OP_ASSIGN_ADD: - case SPL_OP_ASSIGN_SUB: - case SPL_OP_ASSIGN_MUL: - case SPL_OP_ASSIGN_DIV: - case SPL_OP_ASSIGN_MOD: - case SPL_OP_ASSIGN_AND: - case SPL_OP_ASSIGN_OR: - case SPL_OP_ASSIGN_XOR: - case SPL_OP_ASSIGN_LSHIFT: - case SPL_OP_ASSIGN_RSHIFT: { - spl_lang_type_id_t balanced = spl_lang_type_balance(sema->type, lt, rt); - if (balanced == 0 || balanced != lt) { - SPL_ERROR(&n->dbg, "compound assignment type mismatch"); - sema->error_count++; - return 0; - } - spl_ast_node_t *rhs = spl_ast_node(sema->ast, n->binary.right); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, lt, rt); - if (r == 0) { - SPL_ERROR(&n->dbg, "compound assignment right type mismatch"); - sema->error_count++; - return 0; - } - rhs->resolved_lang_tid = r; - n->resolved_lang_tid = lt; - return lt; - } - - case SPL_OP_BOOL_OR: - case SPL_OP_BOOL_AND: { - spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt); - spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt); - if (!ln || ln->kind != SPL_LANG_TYPE_BOOL || !rn || rn->kind != SPL_LANG_TYPE_BOOL) { - SPL_ERROR(&n->dbg, "logical operands must be bool"); - sema->error_count++; - return 0; - } - spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_lang_tid = bt; - return bt; - } - - case SPL_OP_BIT_OR: - case SPL_OP_BIT_XOR: - case SPL_OP_BIT_AND: { - spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt); - spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal); - if (!bn || bn->kind != SPL_LANG_TYPE_INT) { - SPL_ERROR(&n->dbg, "bitwise operands must be integers"); - sema->error_count++; - return 0; - } - /* 两边都 coerce 到 bal */ - if (lt != bal) { - spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left); - ln->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, lt); - } - if (rt != bal) { - spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right); - rn->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, rt); - } - n->resolved_lang_tid = bal; - return bal; - } - - case SPL_OP_CMP_EQ: - case SPL_OP_CMP_NE: - case SPL_OP_CMP_LE: - case SPL_OP_CMP_GE: - case SPL_OP_CMP_LT: - case SPL_OP_CMP_GT: { - spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt); - spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt); - bool numeric = - (ln && (ln->kind == SPL_LANG_TYPE_INT || ln->kind == SPL_LANG_TYPE_FLOAT)) && - (rn && (rn->kind == SPL_LANG_TYPE_INT || rn->kind == SPL_LANG_TYPE_FLOAT)); - if (!numeric && spl_lang_type_balance(sema->type, lt, rt) == 0) { - SPL_ERROR(&n->dbg, "comparison operands type mismatch"); - sema->error_count++; - return 0; - } - spl_lang_type_id_t bt = spl_lang_make_bool(sema->type); - n->resolved_lang_tid = bt; - return bt; - } - - case SPL_OP_LSHIFT: - case SPL_OP_RSHIFT: { - spl_lang_type_node_t *ln = spl_lang_type_node(sema->type, lt); - spl_lang_type_node_t *rn = spl_lang_type_node(sema->type, rt); - if (!ln || ln->kind != SPL_LANG_TYPE_INT || !rn || rn->kind != SPL_LANG_TYPE_INT) { - SPL_ERROR(&n->dbg, "shift operands must be integers"); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = lt; - return lt; - } - - case SPL_OP_ADD: - case SPL_OP_SUB: - case SPL_OP_MUL: - case SPL_OP_DIV: - case SPL_OP_MOD: { - spl_lang_type_id_t bal = spl_lang_type_balance(sema->type, lt, rt); - spl_lang_type_node_t *bn = spl_lang_type_node(sema->type, bal); - if (!bn || (bn->kind != SPL_LANG_TYPE_INT && bn->kind != SPL_LANG_TYPE_FLOAT)) { - SPL_ERROR(&n->dbg, "arithmetic operands type mismatch"); - sema->error_count++; - return 0; - } - if (lt != bal) { - spl_ast_node_t *ln = spl_ast_node(sema->ast, n->binary.left); - ln->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, lt); - } - if (rt != bal) { - spl_ast_node_t *rn = spl_ast_node(sema->ast, n->binary.right); - rn->resolved_lang_tid = spl_lang_type_coerce_to(sema->type, bal, rt); - } - n->resolved_lang_tid = bal; - return bal; - } - - case SPL_OP_RANGE: { - spl_lang_type_id_t i64 = spl_lang_make_int(sema->type, 64, 1); - spl_lang_type_id_t range = spl_lang_make_range(sema->type, i64); - n->resolved_lang_tid = range; - return range; - } - - default: - break; - } - break; - } - - case SPL_AST_EXPR_CALL: { - spl_ast_node_t *callee = spl_ast_node(sema->ast, n->call.callee); - if (callee && callee->kind == SPL_AST_EXPR_IDENT) { - spl_intrin_t in = spl_intrin_lookup_call(callee->ident.name); - if (in != SPL_INTRIN_NONE) { - spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->call.args); - n->resolved_lang_tid = t; - return t; - } - } - - spl_lang_type_id_t callee_tid = sema_parse(sema, n->call.callee); - spl_lang_type_node_t *fn = spl_lang_type_node(sema->type, callee_tid); - if (!fn || fn->kind != SPL_LANG_TYPE_FN) { - SPL_ERROR(&n->dbg, "callee is not a function"); - sema->error_count++; - return 0; - } - - // 检查函数是否可变参数:最后一个参数是否为 VARARGS - bool has_varargs = false; - usize fixed_param_count = vec_size(fn->extra.fn.params); - if (fixed_param_count > 0) { - spl_lang_type_id_t last_param = vec_at(fn->extra.fn.params, fixed_param_count - 1); - spl_lang_type_node_t *last_node = spl_lang_type_node(sema->type, last_param); - if (last_node && last_node->kind == SPL_LANG_TYPE_VARARGS) { - has_varargs = true; - fixed_param_count--; // 排除 VARARGS 参数 - } - } - - if (has_varargs) { - if (vec_size(n->call.args) < fixed_param_count) { - SPL_ERROR(&n->dbg, "too few arguments (expected at least %zu)", fixed_param_count); - sema->error_count++; - } else { - for (usize i = 0; i < fixed_param_count; ++i) { - spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i); - spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref); - spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref); - spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid); - if (r == 0) { - SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); - sema->error_count++; - } else { - arg_node->resolved_lang_tid = r; - } - } - } - } else { - if (vec_size(n->call.args) != vec_size(fn->extra.fn.params)) { - SPL_ERROR(&n->dbg, "argument count mismatch (expected %zu, got %zu)", - vec_size(fn->extra.fn.params), vec_size(n->call.args)); - sema->error_count++; - } else { - for (usize i = 0; i < vec_size(n->call.args); ++i) { - spl_ast_node_ref_t arg_ref = vec_at(n->call.args, i); - spl_ast_node_t *arg_node = spl_ast_node(sema->ast, arg_ref); - spl_lang_type_id_t arg_tid = sema_parse(sema, arg_ref); - spl_lang_type_id_t param_tid = vec_at(fn->extra.fn.params, i); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, param_tid, arg_tid); - if (r == 0) { - SPL_ERROR(&n->dbg, "argument %zu type mismatch", i + 1); - sema->error_count++; - } else { - arg_node->resolved_lang_tid = r; - } - } - } - } - - spl_lang_type_id_t ret_tid = fn->extra.fn.ret; - n->resolved_lang_tid = ret_tid; - return ret_tid; - } - - case SPL_AST_EXPR_FIELD: { - spl_lang_type_id_t obj_tid = sema_parse(sema, n->field.obj); - spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); - if (!obj_node) - return 0; - - spl_intrin_t in = spl_intrin_lookup_field(obj_node->kind, n->field.field); - if (in != SPL_INTRIN_NONE) { - spl_lang_type_id_t t = sema_intrin_field(sema, n, in); - n->resolved_lang_tid = t; - return t; - } - - // 自动解引用 - spl_lang_type_id_t agg_lang = obj_tid; - if (obj_node->kind == SPL_LANG_TYPE_PTR) { - agg_lang = obj_node->extra.elem; - } - spl_lang_type_node_t *agg_node = spl_lang_type_node(sema->type, agg_lang); - if (!agg_node || - (agg_node->kind != SPL_LANG_TYPE_STRUCT && agg_node->kind != SPL_LANG_TYPE_UNION)) { - SPL_ERROR(&n->dbg, "field access on non-aggregate type"); - sema->error_count++; - return 0; - } - spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); - const spl_type_member_t *member = spl_type_agg_member(sema->type, agg_ir, n->field.field); - if (!member) { - SPL_ERROR(&n->dbg, "no field `%s`", n->field.field); - sema->error_count++; - return 0; - } - - // 将底层字段类型映射回语言级类型 - spl_lang_type_id_t field_lang = 0; - for (usize i = 1; i < vec_size(sema->type->lang_table); ++i) { - spl_lang_type_node_t *ln = &vec_at(sema->type->lang_table, i); - if (ln->ir_type_id == member->type_id) { - field_lang = i; - break; - } - } - if (!field_lang) { - SPL_ERROR(&n->dbg, "cannot resolve field type for `%s`", n->field.field); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = field_lang; - return field_lang; - } - - case SPL_AST_EXPR_INDEX: { - spl_lang_type_id_t obj_tid = sema_parse(sema, n->index.obj); - spl_lang_type_id_t idx_tid = sema_parse(sema, n->index.index); - spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); - if (!obj_node) - return 0; - - spl_lang_type_id_t elem_lang = 0; - switch (obj_node->kind) { - case SPL_LANG_TYPE_ARRAY: - case SPL_LANG_TYPE_SLICE: - case SPL_LANG_TYPE_RANGE: - case SPL_LANG_TYPE_PTR: - elem_lang = obj_node->extra.elem; - break; - case SPL_LANG_TYPE_TUPLE: - if (vec_size(obj_node->extra.elems) > 0) - elem_lang = vec_at(obj_node->extra.elems, 0); - else { - SPL_ERROR(&n->dbg, "empty tuple"); - sema->error_count++; - return 0; - } - break; - default: - SPL_ERROR(&n->dbg, "index base must be array, pointer, slice, or tuple"); - sema->error_count++; - return 0; - } - (void)idx_tid; - n->resolved_lang_tid = elem_lang; - return elem_lang; - } - - case SPL_AST_EXPR_SLICE: { - spl_lang_type_id_t obj_tid = sema_parse(sema, n->slice.obj); - if (n->slice.begin) - sema_parse(sema, n->slice.begin); - if (n->slice.end) - sema_parse(sema, n->slice.end); - - spl_lang_type_node_t *obj_node = spl_lang_type_node(sema->type, obj_tid); - if (!obj_node) - return 0; - - spl_lang_type_id_t elem_lang = 0; - if (obj_node->kind == SPL_LANG_TYPE_ARRAY || obj_node->kind == SPL_LANG_TYPE_PTR || - obj_node->kind == SPL_LANG_TYPE_SLICE) { - elem_lang = obj_node->extra.elem; - } else { - SPL_ERROR(&n->dbg, "slice base must be array, pointer, or slice"); - sema->error_count++; - return 0; - } - - spl_lang_type_id_t slice_tid = spl_lang_make_slice(sema->type, elem_lang); - n->resolved_lang_tid = slice_tid; - return slice_tid; - } - - case SPL_AST_EXPR_CAST: { - spl_lang_type_id_t src_tid = sema_parse(sema, n->cast.expr); - spl_lang_type_id_t dst_tid = sema_parse(sema, n->cast.type); - spl_lang_type_node_t *src_node = spl_lang_type_node(sema->type, src_tid); - if (!src_node) - return 0; - if (src_node->kind != SPL_LANG_TYPE_INT && src_node->kind != SPL_LANG_TYPE_FLOAT && - src_node->kind != SPL_LANG_TYPE_BOOL) { - SPL_ERROR(&n->dbg, "invalid cast from non-primitive type"); - sema->error_count++; - return 0; - } - n->resolved_lang_tid = dst_tid; - return dst_tid; - } - - case SPL_AST_EXPR_TUPLE: { - spl_lang_type_id_vec_t elems; - vec_init(elems); - for (usize i = 0; i < vec_size(n->tuple.elems); ++i) { - vec_push(elems, sema_parse(sema, vec_at(n->tuple.elems, i))); - } - spl_lang_type_id_t tuple = - spl_lang_make_tuple(sema->type, vec_unsafe_get_data(elems), vec_size(elems)); - vec_free(elems); - n->resolved_lang_tid = tuple; - return tuple; - } - - case SPL_AST_EXPR_ARRAY_LIT: { - /* elem_type 可空:匿名 .[...] 时从元素推导 */ - spl_lang_type_id_t elem_tid = 0; - if (n->array_literal.elem_type) { - elem_tid = sema_parse(sema, n->array_literal.elem_type); - } - - for (usize i = 0; i < vec_size(n->array_literal.elems); ++i) { - spl_ast_node_ref_t elem_ref = vec_at(n->array_literal.elems, i); - spl_ast_node_t *elem_node = spl_ast_node(sema->ast, elem_ref); - spl_lang_type_id_t et = sema_parse(sema, elem_ref); - if (elem_tid == 0) { - elem_tid = et; - } else { - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, elem_tid, et); - if (r == 0) { - SPL_ERROR(&n->dbg, "array element type mismatch"); - sema->error_count++; - } else { - elem_node->resolved_lang_tid = r; - } - } - } - - if (elem_tid == 0) { - SPL_ERROR(&n->dbg, "cannot infer array element type " - "(empty literal without element type annotation)"); - sema->error_count++; - return 0; - } - - usize len; - if (n->array_literal.is_underscore_len) { - len = vec_size(n->array_literal.elems); - } else if (n->array_literal.has_len) { - len = (usize)n->array_literal.len; - if (len != vec_size(n->array_literal.elems)) { - SPL_ERROR(&n->dbg, "array literal length mismatch: declared %zu, got %zu", len, - vec_size(n->array_literal.elems)); - sema->error_count++; - } - } else { - len = vec_size(n->array_literal.elems); - } - - spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len); - n->resolved_lang_tid = arr_tid; - return arr_tid; - } - case SPL_AST_EXPR_AGGREGATE_LIT: { - const char *type_name = n->aggregate_literal.name; - - /* 匿名 .{...}:需要类型上下文。 - SEMA 当前为自底向上,尚无"预期类型"传播机制; - 待上层注解散布到 init_expr 之前时启用。 - 结构上已统一,只需在这里读取 n->resolved_type_id 即可。 */ - if (!type_name) { - SPL_ERROR(&n->dbg, "anonymous aggregate literal requires expected type context " - "(not yet supported)"); - sema->error_count++; - return 0; - } - - spl_symbol_t sym; - if (!spl_scope_find(sema->scope, type_name, &sym)) { - SPL_ERROR(&n->dbg, "unknown type `%s`", type_name); - sema->error_count++; - return 0; - } - spl_def_node_t *def = spl_def_node(sema->type, sym.node); - if (!def || !def->lang_id) { - SPL_ERROR(&n->dbg, "type `%s` not resolved", type_name); - sema->error_count++; - return 0; - } - spl_lang_type_id_t agg_lang = def->lang_id; - spl_lang_type_node_t *agg_node = spl_lang_type_node(sema->type, agg_lang); - if (!agg_node || - (agg_node->kind != SPL_LANG_TYPE_STRUCT && agg_node->kind != SPL_LANG_TYPE_UNION)) { - SPL_ERROR(&n->dbg, "`%s` is not a struct/union", type_name); - sema->error_count++; - return 0; - } - - spl_type_id_t agg_ir = spl_lang_type_get_ir_type(sema->type, agg_lang); - spl_type_node_t *agg_ir_node = spl_type_node(sema->type, agg_ir); - if (!agg_ir_node) { - SPL_ERROR(&n->dbg, "aggregate IR type `%s` not found", type_name); - sema->error_count++; - return 0; - } - usize total_fields = vec_size(agg_ir_node->agg_type.variants); - - /* 记录每个字段是否被初始化,最后检查缺省 */ - bool *seen = calloc(total_fields, sizeof(bool)); - if (!seen) { - SPL_ERROR(&n->dbg, "out of memory"); - sema->error_count++; - return 0; - } - - for (usize i = 0; i < vec_size(n->aggregate_literal.fields); ++i) { - spl_ast_node_t *item = spl_ast_node(sema->ast, vec_at(n->aggregate_literal.fields, i)); - if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM) - continue; - - const char *fname = item->struct_init_item.name; - usize field_idx = 0; - if (!spl_type_agg_member_idx(sema->type, agg_ir, fname, &field_idx)) { - SPL_ERROR(&item->dbg, "no field `%s` in `%s`", fname, type_name); - sema->error_count++; - continue; - } - if (seen[field_idx]) { - SPL_ERROR(&item->dbg, "duplicate field `%s` in `%s`", fname, type_name); - sema->error_count++; - continue; - } - seen[field_idx] = true; - - const spl_type_member_t *member = &vec_at(agg_ir_node->agg_type.variants, field_idx); - - /* 通过字段的 ir 类型反查 lang 类型 */ - spl_lang_type_id_t expected_lang = 0; - for (usize j = 1; j < vec_size(sema->type->lang_table); ++j) { - spl_lang_type_node_t *ln = &vec_at(sema->type->lang_table, j); - if (ln->ir_type_id == member->type_id) { - expected_lang = j; - break; - } - } - if (!expected_lang) { - SPL_ERROR(&item->dbg, "cannot resolve lang type for field `%s`", fname); - sema->error_count++; - continue; - } - - if (!item->struct_init_item.expr) { - SPL_ERROR(&item->dbg, "field `%s` requires an initializer", fname); - sema->error_count++; - continue; - } - - spl_ast_node_t *fv = spl_ast_node(sema->ast, item->struct_init_item.expr); - spl_lang_type_id_t field_lang = sema_parse(sema, item->struct_init_item.expr); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, expected_lang, field_lang); - if (r == 0) { - SPL_ERROR(&item->dbg, "field `%s` type mismatch", fname); - sema->error_count++; - } else { - fv->resolved_lang_tid = r; - } - } - - /* 检查缺省字段 */ - for (usize i = 0; i < total_fields; ++i) { - if (!seen[i]) { - const spl_type_member_t *m = &vec_at(agg_ir_node->agg_type.variants, i); - SPL_ERROR(&n->dbg, "missing field `%s` in `%s`", m->name, type_name); - sema->error_count++; - } - } - free(seen); - - n->resolved_lang_tid = agg_lang; - return agg_lang; - } - - case SPL_AST_EXPR_COMPTIME_CALL: { - spl_intrin_t in = spl_intrin_lookup_call(n->comptime_call.name); - if (in == SPL_INTRIN_NONE) { - SPL_ERROR(&n->dbg, "unknown comptime call `@%s`", n->comptime_call.name); - sema->error_count++; - return 0; - } - spl_lang_type_id_t t = sema_intrin_call(sema, n, in, &n->comptime_call.args); - n->resolved_lang_tid = t; - return t; - } - - case SPL_AST_EXPR_BLOCK: { - for (usize i = 0; i < vec_size(n->block.stmts); ++i) { - sema_parse(sema, vec_at(n->block.stmts, i)); - } - if (n->block.tail_expr) { - return sema_parse(sema, n->block.tail_expr); - } - return 0; - } - - case SPL_AST_EXPR_IF: { - spl_lang_type_id_t cond_tid = sema_parse(sema, n->if_expr.cond); - spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type); - if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) { - SPL_ERROR(&n->dbg, "if condition must be bool"); - sema->error_count++; - } - - spl_lang_type_id_t then_t = - n->if_expr.then_block ? sema_parse(sema, n->if_expr.then_block) : 0; - spl_lang_type_id_t else_t = - n->if_expr.else_branch ? sema_parse(sema, n->if_expr.else_branch) : 0; - - spl_lang_type_id_t result_t = 0; - if (then_t && else_t) { - result_t = spl_lang_type_balance(sema->type, then_t, else_t); - if (result_t == 0) { - SPL_ERROR(&n->dbg, "if branches type mismatch"); - sema->error_count++; - } else { - if (then_t != result_t) { - spl_ast_node_t *tn = spl_ast_node(sema->ast, n->if_expr.then_block); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, then_t); - if (r) - tn->resolved_lang_tid = r; - } - if (else_t != result_t) { - spl_ast_node_t *en = spl_ast_node(sema->ast, n->if_expr.else_branch); - spl_lang_type_id_t r = spl_lang_type_coerce_to(sema->type, result_t, else_t); - if (r) - en->resolved_lang_tid = r; - } - } - } else { - result_t = then_t ? then_t : else_t; - } - - n->resolved_lang_tid = result_t; - return result_t; - } - - case SPL_AST_EXPR_IFVAR: { - sema_parse(sema, n->ifvar_expr.var_decl); - sema_parse(sema, n->ifvar_expr.then_block); - if (n->ifvar_expr.else_branch) { - sema_parse(sema, n->ifvar_expr.else_branch); - } - return 0; - } - - case SPL_AST_EXPR_WHILE: { - spl_lang_type_id_t cond_tid = sema_parse(sema, n->while_expr.cond); - spl_lang_type_id_t bool_tid = spl_lang_make_bool(sema->type); - if (spl_lang_type_coerce_to(sema->type, bool_tid, cond_tid) == 0) { - SPL_ERROR(&n->dbg, "while condition must be bool"); - sema->error_count++; - } - sema_parse(sema, n->while_expr.body); - if (n->while_expr.else_branch) { - sema_parse(sema, n->while_expr.else_branch); - } - return 0; - } - - case SPL_AST_EXPR_LOOP: { - sema_parse(sema, n->loop_expr.body); - return 0; - } - - case SPL_AST_EXPR_FOR: { - sema_push_scope(sema); - for (usize i = 0; i < vec_size(n->for_expr.iter_exprs); ++i) { - spl_lang_type_id_t container_tid = sema_parse(sema, vec_at(n->for_expr.iter_exprs, i)); - spl_lang_type_id_t elem_tid = sema_for_elem_type(sema, container_tid); - if (i < vec_size(n->for_expr.idents)) { - spl_ast_node_t *id_node = spl_ast_node(sema->ast, vec_at(n->for_expr.idents, i)); - if (id_node && id_node->kind == SPL_AST_EXPR_IDENT) { - const char *var_name = id_node->ident.name; - if (strcmp(var_name, "_") != 0) { - spl_symbol_t sym = {.name = var_name, .kind = SPL_SYMBOL_KIND_VAR}; - sym.node = spl_def_alloc(sema->type, SPL_DEF_VAR, var_name, id_node->dbg, - vec_at(n->for_expr.idents, i)); - spl_def_resolve(sema->type, sym.node, elem_tid); - spl_scope_insert(sema->scope, sema->scope->current_scope, sym); - id_node->resolved_def_id = sym.node; - } - } - } - } - sema_parse(sema, n->for_expr.body); - if (n->for_expr.else_branch) { - sema_parse(sema, n->for_expr.else_branch); - } - sema_pop_scope(sema); - return 0; - } - - case SPL_AST_EXPR_MATCH: { - sema_parse(sema, n->match_expr.matched_expr); - for (usize i = 0; i < vec_size(n->match_expr.arms); ++i) { - spl_ast_node_t *arm = spl_ast_node(sema->ast, vec_at(n->match_expr.arms, i)); - if (arm && arm->kind == SPL_AST_MATCH_ARM) { - sema_parse(sema, arm->match_arm.pattern); - sema_parse(sema, arm->match_arm.body); - } - } - return 0; - } - - case SPL_AST_EXPR_FN_TYPE: { - spl_lang_type_id_vec_t params; - vec_init(params); - for (usize i = 0; i < vec_size(n->fn_type.params); ++i) { - vec_push(params, sema_parse(sema, vec_at(n->fn_type.params, i))); - } - spl_lang_type_id_t ret_tid = sema_parse(sema, n->fn_type.ret_type); - spl_lang_type_id_t fn_tid = - spl_lang_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); - vec_free(params); - n->resolved_lang_tid = fn_tid; - return fn_tid; - } - - case SPL_AST_TYPE_PATH: { - const char *name = n->type_path.name; - - spl_lang_type_id_t builtin = spl_type_lookup_builtin(sema->type, name); - if (builtin != 0) { - n->resolved_lang_tid = builtin; - return builtin; - } - - spl_symbol_t sym; - if (!spl_scope_find(sema->scope, name, &sym)) { - SPL_ERROR(&n->dbg, "type `%s` not found", name); - sema->error_count++; - return 0; - } - spl_def_node_t *def = spl_def_node(sema->type, sym.node); - if (!def || !def->lang_id) - return 0; - n->resolved_lang_tid = def->lang_id; - return def->lang_id; - } - - case SPL_AST_TYPE_POINTER: { - spl_lang_type_id_t pointee_tid = sema_parse(sema, n->type_pointer.pointee); - spl_lang_type_id_t ptr_tid = spl_lang_make_ptr(sema->type, pointee_tid); - n->resolved_lang_tid = ptr_tid; - return ptr_tid; - } - - case SPL_AST_TYPE_ARRAY: { - spl_lang_type_id_t elem_tid = sema_parse(sema, n->type_array.elem_type); - usize len = n->type_array.has_len ? (usize)n->type_array.len : 0; - spl_lang_type_id_t arr_tid = spl_lang_make_array(sema->type, elem_tid, len); - n->resolved_lang_tid = arr_tid; - return arr_tid; - } - - case SPL_AST_TYPE_SLICE: { - spl_lang_type_id_t elem_tid = sema_parse(sema, n->type_slice.elem_type); - spl_lang_type_id_t slice_tid = spl_lang_make_slice(sema->type, elem_tid); - n->resolved_lang_tid = slice_tid; - return slice_tid; - } - - case SPL_AST_TYPE_FN: { - spl_lang_type_id_vec_t params; - vec_init(params); - for (usize i = 0; i < vec_size(n->type_fn.params); ++i) { - vec_push(params, sema_parse(sema, vec_at(n->type_fn.params, i))); - } - spl_lang_type_id_t ret_tid = sema_parse(sema, n->type_fn.ret_type); - spl_lang_type_id_t fn_tid = - spl_lang_make_fn(sema->type, ret_tid, vec_unsafe_get_data(params), vec_size(params)); - vec_free(params); - n->resolved_lang_tid = fn_tid; - return fn_tid; - } - - case SPL_AST_TYPE_PAREN: { - usize count = vec_size(n->type_paren.types); - if (count == 0) { - spl_lang_type_id_t unit = spl_lang_make_unit(sema->type); - n->resolved_lang_tid = unit; - return unit; - } - if (count == 1) { - return sema_parse(sema, vec_at(n->type_paren.types, 0)); - } - - spl_lang_type_id_vec_t elems; - vec_init(elems); - for (usize i = 0; i < count; ++i) { - vec_push(elems, sema_parse(sema, vec_at(n->type_paren.types, i))); - } - spl_lang_type_id_t tuple = - spl_lang_make_tuple(sema->type, vec_unsafe_get_data(elems), vec_size(elems)); - vec_free(elems); - n->resolved_lang_tid = tuple; - return tuple; - } - - case SPL_AST_TYPE_AGGREGATE: { - return 0; - } - - case SPL_AST_TYPE_COMPTIME_CALL: - return 0; - - case SPL_AST_STATEMENT_RET: { - if (n->statement_ret.expr) { - spl_ast_node_t *en = spl_ast_node(sema->ast, n->statement_ret.expr); - spl_lang_type_id_t ret_tid = sema_parse(sema, n->statement_ret.expr); - if (sema->current_fn_ret_tid != 0) { - spl_lang_type_id_t r = - spl_lang_type_coerce_to(sema->type, sema->current_fn_ret_tid, ret_tid); - if (r == 0) { - SPL_ERROR(&n->dbg, "return type mismatch"); - sema->error_count++; - } else { - en->resolved_lang_tid = r; - } - } - } - return 0; - } - case SPL_AST_STATEMENT_BREAK: - case SPL_AST_STATEMENT_CONTINUE: - return 0; - - case SPL_AST_STATEMENT_DEFER: - if (n->statement_defer.body) { - sema_parse(sema, n->statement_defer.body); - } - return 0; - - case SPL_AST_STATEMENT_COMPTIME: - if (n->statement_comptime.body) { - sema_parse(sema, n->statement_comptime.body); - } - return 0; - - case SPL_AST_STATEMENT_DECL: - if (n->statement_decl.decl) { - sema_parse(sema, n->statement_decl.decl); - } - return 0; - - case SPL_AST_STATEMENT_EXPR: - if (n->statement_expr.expr) { - sema_parse(sema, n->statement_expr.expr); - } - return 0; - - default: - return 0; - } - 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_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; sema->type = type; sema->scope = scope; sema->error_count = 0; sema->current_fn_ret_tid = 0; + sema->attr = attr; sema->root = (spl_symbol_t){0}; sema->store_scope = 0; } @@ -2562,7 +1523,7 @@ void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref) { return; spl_scope_id_t saved = sema->scope->current_scope; sema_collect(sema, module_ref); - sema_infer(sema, module_ref); /* 原 sema_parse */ + sema_infer(sema, module_ref); sema->scope->current_scope = saved; } @@ -2606,4 +1567,5 @@ void spl_sema_dump(spl_sema_t *sema) { spl_type_def_dump(sema->type, i); printf("\n"); } + spl_attr_dump(sema->attr); } diff --git a/stage1/spl_sema.h b/stage1/spl_sema.h index 3570004..57ef1bc 100644 --- a/stage1/spl_sema.h +++ b/stage1/spl_sema.h @@ -4,6 +4,8 @@ #include "spl_ast.h" #include "spl_type.h" +#include "spl_attr.h" + typedef enum { SPL_SYMBOL_KIND_ERROR, SPL_SYMBOL_KIND_VAR, @@ -44,10 +46,12 @@ typedef struct { spl_symbol_t root; int error_count; spl_scope_id_t store_scope; + spl_attr_t *attr; spl_type_id_t current_fn_ret_tid; // TODO } 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_type_t *type, spl_scope_t *scope, + spl_attr_t *attr); void spl_sema_drop(spl_sema_t *sema); void spl_sema_run_module(spl_sema_t *sema, spl_ast_node_ref_t module_ref); diff --git a/stage1/splc0.c b/stage1/splc0.c index 7eb288f..0ac29f8 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -91,12 +91,15 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, // memory leak return 0; } + + spl_attr_t attr; + spl_attr_init(&attr); spl_sema_t sema; spl_type_t type; spl_scope_t scope; spl_type_init(&type); spl_scope_init(&scope); - spl_sema_init(&sema, &ast, &type, &scope); + spl_sema_init(&sema, &ast, &type, &scope, &attr); sema.ast = * spl_sema_run(&sema); if (sema.error_count) { @@ -124,13 +127,13 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, return 1; } if (dump == DUMP_IR) { - spl_ir_dump(&ir_builder.ir, &type); + spl_ir_dump(&ir_builder.ir, &type, &attr); // memory leak return 0; } spl_ir2vm_t ir2vm; - spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, sema.type); + spl_ir2vm_init(&ir2vm, &a2ir.ir->ir, &type, &attr); int rc = spl_ir2vm_run(&ir2vm); if (rc != 0) { printf("ir2vm error %d", rc); @@ -148,6 +151,7 @@ static int compile_spl(const char *src, const char *fname, const char *outpath, spl_ast2ir_drop(&a2ir); spl_sema_drop(&sema); spl_ast_drop(&ast); + // memory leak return 0; }