diff --git a/stage0/include/core_map.h b/stage0/include/core_map.h index 5b765e1..096e68f 100644 --- a/stage0/include/core_map.h +++ b/stage0/include/core_map.h @@ -77,6 +77,8 @@ static inline usize map_hash_str(const char *s) { for (usize(idx) = 0; (idx) < (map).cap; ++(idx)) \ if ((map).data[(idx)].state == __MAP_SLOT_OCCUPIED) +#define unsafe_map_at(map, idx) ((map).data[(idx)]) + /** * 插入(若键已存在则更新值) * 注意:扩容使用 realloc,失败会 abort(可自行修改错误处理) diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 0524496..b547d54 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -58,6 +58,7 @@ static inline spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { static spl_ast_node_ref_t new_node(parser_t *p, spl_ast_node_kind_t kind, const spl_tok_t *tok) { spl_ast_node_t n = {0}; n.kind = kind; + n.resolved_def_id = 0; if (tok) { n.dbg.dbg_name = spl_ast_kind_name(kind); n.dbg.fname = tok->fname; @@ -1833,6 +1834,7 @@ void spl_ast_dump(spl_ast_t *ast, spl_ast_node_ref_t node) { return; dump_stack_t stack; vec_init(stack); + printf("AST:\n"); dump_node(ast, node, &stack, 1); } @@ -2109,6 +2111,7 @@ static void dump_node(spl_ast_t *ast, spl_ast_node_ref_t node_ref, dump_stack_t case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: + case SPL_AST_TYPE_SHAPE: dump_vec(ast, node->type_expr.attr_list, stack); dump_vec(ast, node->type_expr.aggregate_list, stack); break; diff --git a/stage1/spl_dbg.h b/stage1/spl_dbg.h index f18a340..ea39824 100644 --- a/stage1/spl_dbg.h +++ b/stage1/spl_dbg.h @@ -1,8 +1,6 @@ #ifndef __SPL_DBG_H__ #define __SPL_DBG_H__ -#include "spl_tok.h" - typedef struct { const char *fname; int line; diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 3491196..724ec1b 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -1,2018 +1,327 @@ -// WRITE BY AI -/* spl_sema.c SPL 语义分析 - * - * 两趟 AST 遍历(splc0 显式先 run 再 check): - * spl_sema_run —— Pass1:预登记顶层名字(聚合壳/别名/fn/var),使兄弟前向引用成立 - * spl_sema_check —— Pass2:边构建聚合成员与方法 def,边检查函数体(类型检查) - * - * scope 符号表存 spl_def_id_t(def 第一公民);匿名类型放 type_table, - * 命名实体放 def_table,两张表 id 空间完全独立。 - */ #include "spl_sema.h" -#include "spl_builtin.h" -#include -#include +// Scope part -typedef struct { - spl_type_id_t ret; -} spl_sema_ctx_t; - -static spl_ast_node_t *node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { - if (!ref || ref >= ast->buckets.size) - return NULL; - return &ast->buckets.data[ref]; +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; } -static void sema_error(spl_sema_t *sema, spl_ast_node_ref_t ref, const char *msg) { - spl_ast_node_t *n = node_at(sema->ast, ref); - sema->error_count++; - if (n) { - LOG_ERROR("%s error: %s (%s:%d:%d)", "sema", msg, n->loc.fname ? n->loc.fname : "?", - n->loc.line, n->loc.col); - } else { - LOG_ERROR("%s error: %s", "sema", msg); +void spl_scope_drop(spl_scope_t *scope) { + 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; + 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) { + if (!id || id >= vec_size(scope->scopes)) { + LOG_FATAL("sema scope insert error"); + return false; } -} - -static void sema_warn(spl_sema_t *sema, spl_ast_node_ref_t ref, const char *msg) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (n) { - LOG_WARN("%s warning: %s (%s:%d:%d)", "sema", msg, n->loc.fname ? n->loc.fname : "?", - n->loc.line, n->loc.col); - } else { - LOG_WARN("%s warning: %s", "sema", msg); + spl_symbol_t old = {0}; + spl_scope_node_t *node = &vec_at(scope->scopes, id); + if (map_get(node->symbols, symbol.name, &old)) { + // spl_type_def(sema->type, old); TODO debug node + LOG_ERROR("find same symbol %s", symbol.name); + return false; } + map_put(node->symbols, symbol.name, symbol); + return true; } -/* ---- def/type 快捷访问 ---- */ - -static spl_def_node_t *def_at(spl_sema_t *sema, spl_def_id_t id) { - return spl_type_def(&sema->type, id); -} - -static spl_type_id_t def_type(spl_sema_t *sema, spl_def_id_t id) { - spl_def_node_t *d = def_at(sema, id); - return d ? d->type_id : 0; -} - -/* 由匿名类型 id 反查拥有它的 def(聚合优先;别名/ distinct 次之) */ -static spl_def_id_t def_for_type(spl_sema_t *sema, spl_type_id_t tid) { - if (!tid) - return 0; - spl_def_id_t fallback = 0; - for (usize i = 1; i < sema->type.def_table.size; i++) { - spl_def_node_t *d = &sema->type.def_table.data[i]; - if (d->type_id == tid) { - if (d->kind == SPL_DEF_AGG) - return i; - if (!fallback && (d->kind == SPL_DEF_ALIAS || d->kind == SPL_DEF_DISTINCT)) - fallback = i; - } +bool spl_scope_find(spl_scope_t *scope, const char *name, spl_symbol_t *out) { + if (scope == NULL || name == NULL || out == NULL) { + return false; } - return fallback; -} - -static spl_def_id_t def_alloc(spl_sema_t *sema, int kind) { - spl_def_id_t id = spl_type_def_alloc(&sema->type); - def_at(sema, id)->kind = kind; - return id; -} - -static spl_def_id_t new_var_def(spl_sema_t *sema, const char *name, spl_type_id_t type, - spl_scope_id_t scope) { - spl_def_id_t id = def_alloc(sema, SPL_DEF_VAR); - spl_def_node_t *d = def_at(sema, id); - d->type_id = type; - d->var_def.name = name; - d->var_def.def_id = id; - d->var_def.type_id = type; - d->var_def.scope_id = scope; - return id; -} - -/* 裸名查找:从 current_scope 沿父链到 root(字段名不在 symbols,天然不命中) */ -static spl_def_id_t find_bare(spl_sema_t *sema, const char *name) { - spl_scope_id_t cur = sema->current_scope; - while (cur) { - if (cur >= sema->scopes.size) + spl_symbol_t symbol = {0}; + for (spl_scope_node_t *s = &vec_at(scope->scopes, scope->current_scope); s->parent != 0; + s = &vec_at(scope->scopes, s->parent)) { + if (map_get(s->symbols, name, &symbol) == true) { + Assert(symbol.kind != SPL_SYMBOL_KIND_ERROR); break; - spl_def_id_t val = 0; - if (map_get(sema->scopes.data[cur].symbols, name, &val)) - return val; - cur = sema->scopes.data[cur].parent; - } - return 0; -} - -/* 名字 → 其类型(def → type_id) */ -static spl_type_id_t find_type(spl_sema_t *sema, const char *name) { - return def_type(sema, find_bare(sema, name)); -} - -/* ---- 聚合成员登记(def 层 agg_def) ---- */ - -static void agg_add_member(spl_sema_t *sema, spl_def_id_t def, const char *name, spl_type_id_t type, - spl_scope_id_t scope, spl_def_id_t member_def) { - spl_def_node_t *d = def_at(sema, def); - if (!d || d->kind != SPL_DEF_AGG) - return; - spl_var_def_t v = {name, member_def, type, scope}; - vec_push(d->agg_def, v); -} - -/* 聚合/枚举成员查找:匿名类型 id → 拥有它的 def → agg_def */ -static spl_type_id_t agg_member_type(spl_sema_t *sema, spl_type_id_t agg_tid, const char *name) { - spl_def_id_t d = def_for_type(sema, agg_tid); - if (!d) - return 0; - spl_def_node_t *def = def_at(sema, d); - for (usize i = 0; i < def->agg_def.size; i++) { - if (def->agg_def.data[i].name && strcmp(def->agg_def.data[i].name, name) == 0) - return def->agg_def.data[i].type_id; - } - return 0; -} - -/* ---- 类型解析 ---- */ - -static spl_type_id_t resolve_type_expr(spl_sema_t *sema, spl_ast_node_ref_t ref); -static spl_type_id_t resolve_type_atom(spl_sema_t *sema, spl_ast_node_ref_t ref); -static spl_type_id_t build_agg(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t parent, - const char *name); - -/* 路径类型:首段裸名(含内置),后续段逐级查聚合 agg_def */ -static spl_type_id_t resolve_type_path(spl_sema_t *sema, spl_ast_node_ref_vec_t *path) { - if (!path->size) - return 0; - spl_type_id_t tid = resolve_type_atom(sema, path->data[0]); - if (!tid) - return 0; - for (usize i = 1; i < path->size; i++) { - spl_ast_node_t *atom = node_at(sema->ast, path->data[i]); - if (!atom) { - sema_error(sema, path->data[i], "bad type path segment"); - return 0; - } - spl_type_id_t mt = agg_member_type(sema, tid, atom->type_atom.ident); - if (!mt) { - char buf[128]; - snprintf(buf, sizeof buf, "no member '%s' in type", atom->type_atom.ident); - sema_error(sema, path->data[i], buf); - return 0; - } - tid = mt; - } - return tid; -} - -static spl_type_id_t resolve_type_atom(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return 0; - switch (n->type_atom.kind) { - case SPL_AST_TYPE_VOID: - return spl_type_void(&sema->type); - case SPL_AST_TYPE_BOOL: - return spl_type_bool(&sema->type); - case SPL_AST_TYPE_I8: - return spl_type_int(&sema->type, 8, 1); - case SPL_AST_TYPE_U8: - return spl_type_int(&sema->type, 8, 0); - case SPL_AST_TYPE_I16: - return spl_type_int(&sema->type, 16, 1); - case SPL_AST_TYPE_U16: - return spl_type_int(&sema->type, 16, 0); - case SPL_AST_TYPE_I32: - return spl_type_int(&sema->type, 32, 1); - case SPL_AST_TYPE_U32: - return spl_type_int(&sema->type, 32, 0); - case SPL_AST_TYPE_I64: - return spl_type_int(&sema->type, 64, 1); - case SPL_AST_TYPE_U64: - return spl_type_int(&sema->type, 64, 0); - case SPL_AST_TYPE_ISIZE: - return spl_type_int(&sema->type, sizeof(isize) * 8, 1); - case SPL_AST_TYPE_USIZE: - return spl_type_int(&sema->type, sizeof(usize) * 8, 0); - case SPL_AST_TYPE__F32: - return spl_type_float(&sema->type, 32); - case SPL_AST_TYPE__F64: - return spl_type_float(&sema->type, 64); - case SPL_AST_TYPE_PTR: - case SPL_AST_TYPE_ANY: - /* `_`/`ptr` 均为通配:只能作为指针目标,等于 *void。 - * 裸用(无 * 前缀)由 resolve_type_expr 报错;ptr 关键字暂不使用 */ - return spl_type_void(&sema->type); - case SPL_AST_TYPE_IDENT: { - spl_type_id_t tid = find_type(sema, n->type_atom.ident); - if (!tid) { - char buf[160]; - snprintf(buf, sizeof buf, "unknown type '%s'", n->type_atom.ident); - sema_error(sema, ref, buf); - return 0; - } - return tid; - } - } - return 0; -} - -static spl_type_id_t resolve_type_expr(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return 0; - spl_type_id_t base = 0; - switch (n->type_expr.kind) { - case SPL_AST_BASE_TYPE_PATH: - base = resolve_type_path(sema, &n->type_expr.type_path); - break; - case SPL_AST_BASE_TYPE_FN: { - spl_type_id_vec_t params; - vec_init(params); - for (usize i = 0; i < n->type_expr.fn_type.param_list.size; i++) { - spl_ast_node_t *pd = node_at(sema->ast, n->type_expr.fn_type.param_list.data[i]); - spl_type_id_t pt = 0; - if (pd && pd->param_decl.type_expr) - pt = resolve_type_expr(sema, pd->param_decl.type_expr); - vec_push(params, pt); - } - spl_type_id_t ret = 0; - if (n->type_expr.fn_type.type_expr) - ret = resolve_type_expr(sema, n->type_expr.fn_type.type_expr); - else - ret = spl_type_void(&sema->type); - base = spl_type_fn(&sema->type, params, ret); - break; - } - case SPL_AST_TYPE_STRUCT: - case SPL_AST_TYPE_UNION: - case SPL_AST_TYPE_ENUM: - /* 内联匿名聚合:构建聚合类型(不注册名字,parent 为当前 scope) */ - base = build_agg(sema, ref, sema->current_scope, NULL); - break; - default: - return 0; - } - /* 前缀修饰:* → ptr,[] → slice,[n] → array(逆序包裹) */ - for (usize i = n->type_expr.type_prefixs.size; i > 0; i--) { - spl_ast_node_t *pf = node_at(sema->ast, n->type_expr.type_prefixs.data[i - 1]); - if (!pf) - continue; - if (pf->prefix_type.pointer == 1) { - base = spl_type_ptr(&sema->type, base); - } else if (pf->prefix_type.pointer == 2) { - if (pf->prefix_type.array_size > 0) - base = spl_type_array(&sema->type, base, (usize)pf->prefix_type.array_size); - else - base = spl_type_slice(&sema->type, base); } } - /* `_`/`ptr` 只能在指针目标位置(*_ = *void);裸用是无类型值,报错 */ - if (n->type_expr.kind == SPL_AST_BASE_TYPE_PATH && n->type_expr.type_path.size) { - spl_ast_node_t *atom = - node_at(sema->ast, n->type_expr.type_path.data[n->type_expr.type_path.size - 1]); - int ptr_pre = 0; - for (usize i = 0; i < n->type_expr.type_prefixs.size; i++) { - spl_ast_node_t *pf = node_at(sema->ast, n->type_expr.type_prefixs.data[i]); - if (pf && pf->prefix_type.pointer == 1) - ptr_pre = 1; + if (symbol.kind == SPL_SYMBOL_KIND_ERROR) { + return false; + } + return true; +} + +// Parse once +static void sema_collect(spl_sema_t *sema, spl_ast_node_ref_t ref) { + Assert(sema != NULL && ref != 0); + spl_ast_node_t *n = spl_ast_node(sema->ast, ref); + spl_symbol_t symbol = {0}; + spl_def_id_t def = 0; + Assert(n != NULL); + switch (n->kind) { + case SPL_AST_CONTAINER_MEMBERS: { + symbol.name = "$file"; + symbol.kind = SPL_SYMBOL_KIND_TYPE; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; + + spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); + sema->scope->current_scope = scope_id; + sema->scope->root_scope = scope_id; + spl_scope_insert(sema->scope, scope_id, symbol); + vec_for(n->container_members, i) { sema_collect(sema, vec_at(n->container_members, i)); } + + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + def->kind = SPL_DEF_AGG; + break; + } + case SPL_AST_TYPE_DECL: { + symbol.name = n->type_decl.name; + symbol.kind = SPL_SYMBOL_KIND_TYPE; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; + n = spl_ast_node(sema->ast, n->type_decl.type_expr); + if (!n) { + SPL_FATAL(&n->dbg, "type_decl must have type_expr"); + return; } - if (atom && !ptr_pre && - (atom->type_atom.kind == SPL_AST_TYPE_ANY || atom->type_atom.kind == SPL_AST_TYPE_PTR)) - sema_error(sema, ref, "bare `_` type only allowed as pointer target `*_`"); - } - /* AST 注解:该 type_expr 解析到的 def(聚合/别名/内置为 0;ast2ir 据此直接取类型) */ - if (base) - n->resolved_def_id = def_for_type(sema, base); - return base; -} -/* ---- 声明处理 ---- */ - -static void sema_fn_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def); -static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def); -static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def); -static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def); -static void check_fn_body(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_def_id_t fdef, - spl_scope_id_t parent_scope); - -typedef struct { - spl_type_id_t tid; - spl_def_id_t def; -} agg_handle_t; - -/* 只建匿名聚合类型 + AGG def(名字由调用方注册到目标 scope),不做成员解析。 - * 用于顶层聚合在 Pass1 预登记,使兄弟/自引用 `type Node{next:*Node}` 成立。 */ -static agg_handle_t agg_prepare(spl_sema_t *sema, spl_ast_node_ref_t ref) { - agg_handle_t h = {0, 0}; - spl_ast_node_t *te = node_at(sema->ast, ref); - if (!te) - return h; - spl_type_id_t tid = spl_type_alloc(&sema->type); - spl_type_node_t *tn = spl_type_node(&sema->type, tid); - switch (te->type_expr.kind) { - case SPL_AST_TYPE_STRUCT: - tn->kind = SPL_TYPE_STRUCT; - vec_init(tn->agg_field_types); - break; - case SPL_AST_TYPE_UNION: - tn->kind = SPL_TYPE_UNION; - vec_init(tn->agg_field_types); - break; - case SPL_AST_TYPE_ENUM: - tn->kind = SPL_TYPE_ENUM; - vec_init(tn->enum_type.variants); - tn->enum_type.tag_type = 0; - break; - default: - return h; /* 非聚合 */ - } - spl_def_id_t def = def_alloc(sema, SPL_DEF_AGG); - def_at(sema, def)->type_id = tid; - vec_init(def_at(sema, def)->agg_def); - te->resolved_def_id = def; /* 注解:该 type_expr 解析到的 def */ - h.tid = tid; - h.def = def; - return h; -} - -/* 聚合成员解析:建聚合 scope(自名注册)→ 嵌套类型 pass1 → 成员/方法 pass2 → 方法体 pass3 */ -static void agg_resolve(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_type_id_t tid, - spl_def_id_t def, spl_scope_id_t parent, const char *name) { - spl_ast_node_t *te = node_at(sema->ast, ref); - if (!te) - return; - spl_scope_id_t agg_scope = spl_sema_scope_alloc(sema); - sema->scopes.data[agg_scope].parent = parent; - if (name) - spl_sema_scope_insert(sema, agg_scope, name, def); - spl_scope_id_t save = sema->current_scope; - sema->current_scope = agg_scope; - /* pass1: 先构建嵌套类型(type 声明),使字段类型可前向引用嵌套类型 */ - for (usize i = 0; i < te->type_expr.aggregate_list.size; i++) { - spl_ast_node_t *m = node_at(sema->ast, te->type_expr.aggregate_list.data[i]); - if (m && m->kind == SPL_AST_TYPE_DECL) - sema_type_decl(sema, te->type_expr.aggregate_list.data[i], agg_scope, def); - } - /* pass2: 成员 + 方法 def(兄弟方法全部登记后再检查体) */ - for (usize i = 0; i < te->type_expr.aggregate_list.size; i++) { - spl_ast_node_ref_t mref = te->type_expr.aggregate_list.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m) - continue; - switch (m->kind) { - case SPL_AST_MEMBER_DECL: { - spl_type_id_t ft = - m->member_decl.type_expr ? resolve_type_expr(sema, m->member_decl.type_expr) : 0; - /* resolve_type_expr 可能 alloc 新类型 → 两表 realloc,须重新取节点 */ - spl_type_node_t *tn = spl_type_node(&sema->type, tid); - /* 每个 MEMBER_DECL 建一个 SPL_DEF_MEMBER def(结构字段/枚举变体) */ - spl_type_id_t mtype = 0; - if (tn->kind == SPL_TYPE_ENUM) { - mtype = ft ? ft : tid; /* 哨兵:无载荷变体 = 枚举自身 tid */ - vec_push(tn->enum_type.variants, mtype); - } else { - mtype = ft; - vec_push(tn->agg_field_types, ft); + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + switch (n->kind) { + case SPL_AST_TYPE_STRUCT: + case SPL_AST_TYPE_UNION: + case SPL_AST_TYPE_ENUM: + case SPL_AST_TYPE_SHAPE: /* TODO for shape */ + def->kind = SPL_DEF_AGG; + spl_scope_id_t scope_id = spl_scope_alloc(sema->scope); + spl_scope_id_t old_id = sema->scope->current_scope; + spl_scope_insert(sema->scope, old_id, symbol); + sema->scope->current_scope = scope_id; + vec_for(n->type_expr.aggregate_list, i) { + sema_collect(sema, vec_at(n->type_expr.aggregate_list, i)); } - spl_def_id_t mdef = def_alloc(sema, SPL_DEF_MEMBER); - def_at(sema, mdef)->type_id = mtype; - def_at(sema, mdef)->var_def.name = m->member_decl.name; - agg_add_member(sema, def, m->member_decl.name, mtype, agg_scope, mdef); - m->resolved_def_id = mdef; /* 注解:member_decl → 其 SPL_DEF_MEMBER def */ - break; - } - case SPL_AST_FN_DECL: - case SPL_AST_FN_DEFINE: - sema_fn_decl(sema, mref, agg_scope, def); - break; - case SPL_AST_TYPE_DECL: - /* 已在 pass1 处理 */ - break; - case SPL_AST_VAR_DECL: - sema_var_decl(sema, mref, agg_scope, def); - break; - case SPL_AST_CONST_DECL: - sema_const_decl(sema, mref, agg_scope, def); + sema->scope->current_scope = old_id; break; default: + def->kind = SPL_DEF_SCALAR; break; } - } - /* pass3: 检查方法体(当前聚合所有方法已登记,兄弟可互调) */ - for (usize i = 0; i < te->type_expr.aggregate_list.size; i++) { - spl_ast_node_ref_t mref = te->type_expr.aggregate_list.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (m && m->kind == SPL_AST_FN_DEFINE) { - spl_def_id_t mdef = find_bare(sema, m->fn_decl.name); - check_fn_body(sema, mref, mdef, agg_scope); - } - } - sema->current_scope = save; -} + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } break; + case SPL_AST_FN_DECL: + case SPL_AST_FN_DEFINE: { + symbol.name = n->fn_decl.name; + symbol.kind = SPL_SYMBOL_KIND_FN; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; -/* 嵌套/内联聚合:prepare + resolve 一步完成 */ -static spl_type_id_t build_agg(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t parent, - const char *name) { - agg_handle_t h = agg_prepare(sema, ref); - if (!h.tid) - return 0; - agg_resolve(sema, ref, h.tid, h.def, parent, name); - return h.tid; -} + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + def->kind = SPL_DEF_FN_PARAMS; + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } break; + case SPL_AST_VAR_DECL: + case SPL_AST_CONST_DECL: { + symbol.name = n->var_const_decl.name; + symbol.kind = SPL_SYMBOL_KIND_VAR; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; -/* 变量/常量/绑定节点:建 VAR def(不包 SPL_TYPE_ID) */ -static void register_binding(spl_sema_t *sema, const char *name, spl_ast_node_ref_t type_expr, - spl_scope_id_t scope, spl_def_id_t agg_def, - spl_ast_node_ref_t node_ref) { - spl_type_id_t t = type_expr ? resolve_type_expr(sema, type_expr) : 0; - spl_def_id_t def = new_var_def(sema, name, t, scope); - if (!spl_sema_scope_insert(sema, scope, name, def)) - sema_error(sema, 0, "duplicate symbol"); - if (agg_def) - agg_add_member(sema, agg_def, name, t, scope, def); - if (node_ref) { - spl_ast_node_t *nn = node_at(sema->ast, node_ref); - if (nn) - nn->resolved_def_id = def; /* 注解:var/const 声明 → 其 VAR def */ + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + def->kind = SPL_DEF_VAR; + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } break; + case SPL_AST_MEMBER_DECL: { + symbol.name = n->member_decl.name; + symbol.kind = SPL_SYMBOL_KIND_MEMBER; + symbol.node = spl_type_def_alloc(sema->type); + n->resolved_def_id = symbol.node; + + spl_def_node_t *def = spl_type_def(sema->type, symbol.node); + def->kind = SPL_DEF_MEMBER; + spl_scope_insert(sema->scope, sema->scope->current_scope, symbol); + } break; + default: + break; } } -static void sema_var_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return; - register_binding(sema, n->var_decl.name, n->var_decl.type_expr, scope, agg_def, ref); -} - -static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return; - register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def, ref); - /* 标记 const:赋值检查拒绝写入 */ - spl_ast_node_t *nn = node_at(sema->ast, ref); - if (nn && nn->resolved_def_id) { - spl_def_node_t *d = def_at(sema, nn->resolved_def_id); - if (d) - d->var_def.is_const = 1; - } -} - -/* fn 声明:建 fn type + FN_PARAMS def + 登记名字。不建 fn_scope(由 check 新建)。 - * 形参只把 name/type 记入 fn_params_def(def_id=0),实际参数 def 在 check 时创建。 */ -static void sema_fn_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return; - spl_type_id_vec_t params; - vec_init(params); - for (usize i = 0; i < n->fn_decl.param_list.size; i++) { - spl_ast_node_t *pd = node_at(sema->ast, n->fn_decl.param_list.data[i]); - spl_type_id_t pt = 0; - if (pd && pd->param_decl.type_expr) - pt = resolve_type_expr(sema, pd->param_decl.type_expr); - vec_push(params, pt); - } - spl_type_id_t ret = 0; - if (n->fn_decl.type_expr) - ret = resolve_type_expr(sema, n->fn_decl.type_expr); - else - ret = spl_type_void(&sema->type); - spl_type_id_t fid = spl_type_fn(&sema->type, params, ret); - spl_def_id_t fdef = def_alloc(sema, SPL_DEF_FN_PARAMS); - spl_def_node_t *d = def_at(sema, fdef); - d->type_id = fid; - vec_init(d->fn_params_def); - for (usize i = 0; i < n->fn_decl.param_list.size; i++) { - spl_ast_node_t *pd = node_at(sema->ast, n->fn_decl.param_list.data[i]); - if (!pd) - continue; - spl_var_def_t pv = {pd->param_decl.name, 0, params.data[i], 0}; - vec_push(d->fn_params_def, pv); - } - if (!spl_sema_scope_insert(sema, scope, n->fn_decl.name, fdef)) - sema_error(sema, ref, "duplicate function name"); - if (agg_def) - agg_add_member(sema, agg_def, n->fn_decl.name, fid, scope, fdef); - n->resolved_def_id = fdef; /* 注解:fn 声明 → 其 FN_PARAMS def */ -} - -static void sema_type_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_id_t scope, - spl_def_id_t agg_def) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return; - spl_ast_node_t *te = node_at(sema->ast, n->type_decl.type_expr); - spl_type_id_t tid = 0; +// Parse twice +static void sema_parse(spl_sema_t *sema, spl_ast_node_ref_t ref) { + Assert(sema != NULL && ref != 0); + spl_ast_node_t *n = spl_ast_node(sema->ast, ref); + spl_symbol_t symbol = {0}; spl_def_id_t def = 0; - if (te && - (te->type_expr.kind == SPL_AST_TYPE_STRUCT || te->type_expr.kind == SPL_AST_TYPE_UNION || - te->type_expr.kind == SPL_AST_TYPE_ENUM)) { - agg_handle_t h = agg_prepare(sema, n->type_decl.type_expr); - tid = h.tid; - def = h.def; - agg_resolve(sema, n->type_decl.type_expr, h.tid, h.def, scope, n->type_decl.name); - } else if (te) { - tid = resolve_type_expr(sema, n->type_decl.type_expr); - def = def_alloc(sema, SPL_DEF_ALIAS); - spl_def_node_t *d = def_at(sema, def); - d->type_id = tid; - d->type_def.name = n->type_decl.name; - d->type_def.def_id = def; - d->type_def.type_id = tid; - d->type_def.scope_id = scope; - } - if (!tid || !def) - return; - if (!spl_sema_scope_insert(sema, scope, n->type_decl.name, def)) - sema_error(sema, ref, "duplicate type name"); - if (agg_def) - agg_add_member(sema, agg_def, n->type_decl.name, tid, scope, def); - /* 嵌套类型提升到文件作用域:兄弟聚合可裸名引用(如 Lexer 方法内 Tag.eof) */ - if (agg_def) - spl_sema_scope_insert(sema, sema->root_scope, n->type_decl.name, def); - n->resolved_def_id = def; /* 注解:type_decl → 其 AGG/ALIAS def */ -} - -/* ================================================================ - * 类型检查(阶段 B) - * ================================================================ */ - -static spl_type_id_t infer_expr(spl_sema_t *sema, spl_ast_node_ref_t ref); - -/* 类型节点快捷查询 */ -static spl_type_node_t *type_node(spl_sema_t *sema, spl_type_id_t tid) { - return spl_type_node(&sema->type, tid); -} - -static bool is_int_tid(spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = type_node(sema, tid); - return t && t->kind == SPL_TYPE_INT; -} - -static bool is_numeric_tid(spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = type_node(sema, tid); - return t && (t->kind == SPL_TYPE_INT || t->kind == SPL_TYPE_FLOAT); -} - -static bool is_agg_tid(spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = type_node(sema, tid); - return t && - (t->kind == SPL_TYPE_STRUCT || t->kind == SPL_TYPE_UNION || t->kind == SPL_TYPE_ENUM); -} - -/* 表达式是否为整数字面量(含一元负号) */ -static bool expr_is_int_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n || n->kind != SPL_AST_EXPR) - return false; - switch (n->expr.op) { - case SPL_AST_PRIMARY_EXPR: { - spl_ast_node_t *pn = node_at(sema->ast, n->expr.op_expr.left); - int k = pn && pn->kind == SPL_AST_EXPR ? (int)pn->primary_expr.kind : -1; - return k == SPL_AST_INTEGER || k == SPL_AST_CHAR_LIT; - } - case SPL_AST_PREFIX_EXPR: - return expr_is_int_literal(sema, n->expr.op_expr.left); - default: - return false; - } -} - -/* 浮点字面量(含负号前缀):允许拓宽/窄化到目标浮点类型 */ -static bool expr_is_float_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n || n->kind != SPL_AST_EXPR) - return false; - switch (n->expr.op) { - case SPL_AST_PRIMARY_EXPR: { - spl_ast_node_t *pn = node_at(sema->ast, n->expr.op_expr.left); - int k = pn && pn->kind == SPL_AST_EXPR ? (int)pn->primary_expr.kind : -1; - return k == SPL_AST_FLOAT; - } - case SPL_AST_PREFIX_EXPR: - return expr_is_float_literal(sema, n->expr.op_expr.left); - default: - return false; - } -} - -/* 字面量(整型或浮点):检查时允许类型拓宽 */ -static bool expr_is_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { - return expr_is_int_literal(sema, ref) || expr_is_float_literal(sema, ref); -} - -/* 打开 SPL_TYPE_ID 绑定节点,返回真实类型(newtype 预留;当前无调用产生该节点) */ -static spl_type_id_t underlying(spl_sema_t *sema, spl_type_id_t tid) { - spl_type_node_t *t = type_node(sema, tid); - if (t && t->kind == SPL_TYPE_ID) - return t->type_id; - return tid; -} - -/* 结构递归相等:ptr/slice/array/fn 等构造类型按结构比较, - * 因为 spl_type_ptr/slice/array 不去重,相同结构可能有不同 id */ -static int type_same(spl_sema_t *sema, spl_type_id_t a, spl_type_id_t b) { - if (a == b) - return 1; - a = underlying(sema, a); - b = underlying(sema, b); - if (a == b) - return 1; - spl_type_node_t *na = type_node(sema, a); - spl_type_node_t *nb = type_node(sema, b); - if (!na || !nb || na->kind != nb->kind) - return 0; - switch (na->kind) { - case SPL_TYPE_INT: - return na->int_type.bits == nb->int_type.bits && - na->int_type.is_signed == nb->int_type.is_signed; - case SPL_TYPE_FLOAT: - return na->float_type.bits == nb->float_type.bits; - case SPL_TYPE_PTR: - return type_same(sema, na->ptr_pointee, nb->ptr_pointee); - case SPL_TYPE_SLICE: - return type_same(sema, na->slice_element, nb->slice_element); - case SPL_TYPE_RANGE: - return type_same(sema, na->range_element, nb->range_element); - case SPL_TYPE_ARRAY: - return na->array_type.len == nb->array_type.len && - type_same(sema, na->array_type.element, nb->array_type.element); - case SPL_TYPE_FN: { - if (na->fn_type.params.size != nb->fn_type.params.size) - return 0; - for (usize i = 0; i < na->fn_type.params.size; i++) - if (!type_same(sema, na->fn_type.params.data[i], nb->fn_type.params.data[i])) - return 0; - return type_same(sema, na->fn_type.ret, nb->fn_type.ret); - } - default: - return 0; - } -} - -/* 兼容性检查:src 可赋给 dst?is_literal 表示 src 是整数字面量 */ -/* 返回值:1 兼容,0 不兼容 */ -static int type_compatible(spl_sema_t *sema, spl_type_id_t dst, spl_type_id_t src, int is_literal, - int *warned) { - if (warned) - *warned = 0; - if (!dst || !src) - return 0; - dst = underlying(sema, dst); - src = underlying(sema, src); - spl_type_node_t *d = type_node(sema, dst); - spl_type_node_t *s = type_node(sema, src); - if (!d || !s) - return 0; - if (type_same(sema, dst, src)) - return 1; - /* 整数字面量可拓宽到目标整数 */ - if (is_literal && d->kind == SPL_TYPE_INT && s->kind == SPL_TYPE_INT) { - /* 字面量值已隐含满足范围(检查时由调用方保证),此处允许拓宽 */ - return 1; - } - /* 浮点字面量可赋值到目标浮点(f64 字面量 → f32 变量,值可表示则允许) */ - if (is_literal && d->kind == SPL_TYPE_FLOAT && s->kind == SPL_TYPE_FLOAT) - return 1; - /* isize/usize(机器字宽)与 i32 混合:比较/算术/传参可用(splc1 与旧测试事实标准) */ - if (d->kind == SPL_TYPE_INT && s->kind == SPL_TYPE_INT) { - int dbits = d->int_type.bits, sbits = s->int_type.bits; - int word = (int)(sizeof(usize) * 8); - if ((dbits == word && sbits == 32) || (dbits == 32 && sbits == word)) { - if (warned) - *warned = 1; - return 1; - } - } - /* 数组 [N]T -> 切片 []T */ - if (d->kind == SPL_TYPE_SLICE && s->kind == SPL_TYPE_ARRAY) { - if (d->slice_element == s->array_type.element) - return 1; - } - /* *T -> *_ 与 *_ -> *T(警告转换;*_ 即 *void) */ - if (d->kind == SPL_TYPE_PTR && s->kind == SPL_TYPE_PTR) { - spl_type_id_t void_t = spl_type_void(&sema->type); - if (d->ptr_pointee == void_t && s->ptr_pointee != void_t) { - if (warned) - *warned = 1; - return 1; - } - if (s->ptr_pointee == void_t && d->ptr_pointee != void_t) { - if (warned) - *warned = 1; - return 1; - } - /* *T -> *u8:字节指针视图(splc1 事实标准,如 vm_fwrite(buf:*u8, &x)) */ - spl_type_node_t *dtn = type_node(sema, d->ptr_pointee); - if (dtn && dtn->kind == SPL_TYPE_INT && dtn->int_type.bits == 8 && - dtn->int_type.is_signed == 0 && !type_same(sema, d->ptr_pointee, s->ptr_pointee)) { - if (warned) - *warned = 1; - return 1; - } - } - return 0; -} - -/* expr 是否为 null 字面量(不参与类型推导,需上下文) */ -static bool expr_is_null_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n || n->kind != SPL_AST_EXPR) - return false; - if (n->expr.op == SPL_AST_PRIMARY_EXPR) - return expr_is_null_literal(sema, n->expr.op_expr.left); - return n->primary_expr.kind == SPL_AST_NULL; -} - -/* 二元算术/位运算:两侧类型一致,或整数字面量拓宽;含指针算术 *T + int */ -static spl_type_id_t infer_binary_arith(spl_sema_t *sema, spl_ast_node_ref_t ref, - spl_ast_node_t *e) { - spl_type_id_t l = infer_expr(sema, e->expr.op_expr.left); - spl_type_id_t r = infer_expr(sema, e->expr.op_expr.right); - if (!l || !r) { - sema_error(sema, ref, "bad operand in arithmetic"); - return 0; - } - l = underlying(sema, l); - r = underlying(sema, r); - /* 指针算术:*T + int / int + *T / *T - int → *T */ - if (e->expr.op == SPL_AST_ADD_EXPR || e->expr.op == SPL_AST_SUB_EXPR) { - spl_type_node_t *lt = type_node(sema, l); - spl_type_node_t *rt = type_node(sema, r); - if (lt && lt->kind == SPL_TYPE_PTR && rt && is_int_tid(sema, r)) - return l; - if (rt && rt->kind == SPL_TYPE_PTR && lt && is_int_tid(sema, l) && - e->expr.op == SPL_AST_ADD_EXPR) - return r; - } - if (l == r) { - if (!is_numeric_tid(sema, l)) { - sema_error(sema, ref, "arithmetic requires numeric operands"); - return 0; - } - return l; - } - int ll = expr_is_int_literal(sema, e->expr.op_expr.left); - int rl = expr_is_int_literal(sema, e->expr.op_expr.right); - if (ll && is_int_tid(sema, r)) { - int w = 0; - if (type_compatible(sema, r, l, 1, &w)) - return r; - } - if (rl && is_int_tid(sema, l)) { - int w = 0; - if (type_compatible(sema, l, r, 1, &w)) - return l; - } - /* isize/usize 与 i32 混合算术:结果取左操作数类型 */ - if (is_int_tid(sema, l) && is_int_tid(sema, r)) { - int w = 0; - if (type_compatible(sema, l, r, 0, &w)) - return l; - } - sema_error(sema, ref, "type mismatch in arithmetic"); - return 0; -} - -/* 比较运算:兼容则返回 bool */ -static spl_type_id_t infer_binary_cmp(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *e) { - spl_type_id_t l = infer_expr(sema, e->expr.op_expr.left); - spl_type_id_t r = infer_expr(sema, e->expr.op_expr.right); - /* null 与指针比较合法 */ - if (expr_is_null_literal(sema, e->expr.op_expr.left)) { - if (r && type_node(sema, underlying(sema, r))->kind == SPL_TYPE_PTR) - return spl_type_bool(&sema->type); - sema_error(sema, ref, "null can only compare with pointers"); - return 0; - } - if (expr_is_null_literal(sema, e->expr.op_expr.right)) { - if (l && type_node(sema, underlying(sema, l))->kind == SPL_TYPE_PTR) - return spl_type_bool(&sema->type); - sema_error(sema, ref, "null can only compare with pointers"); - return 0; - } - if (!l || !r) { - sema_error(sema, ref, "bad operand in comparison"); - return 0; - } - int w = 0; - if (type_compatible(sema, l, r, expr_is_literal(sema, e->expr.op_expr.right), &w) || - type_compatible(sema, r, l, expr_is_literal(sema, e->expr.op_expr.left), &w)) { - return spl_type_bool(&sema->type); - } - sema_error(sema, ref, "type mismatch in comparison"); - return 0; -} - -/* 逻辑运算:两侧 bool */ -static spl_type_id_t infer_binary_logic(spl_sema_t *sema, spl_ast_node_ref_t ref, - spl_ast_node_t *e) { - spl_type_id_t l = infer_expr(sema, e->expr.op_expr.left); - spl_type_id_t r = infer_expr(sema, e->expr.op_expr.right); - if (underlying(sema, l) != underlying(sema, spl_type_bool(&sema->type)) || - underlying(sema, r) != underlying(sema, spl_type_bool(&sema->type))) { - sema_error(sema, ref, "logical operators require bool operands"); - return 0; - } - return spl_type_bool(&sema->type); -} - -/* 位运算:两侧整数同型或字面量拓宽 */ -static spl_type_id_t infer_binary_bit(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *e) { - spl_type_id_t l = infer_expr(sema, e->expr.op_expr.left); - spl_type_id_t r = infer_expr(sema, e->expr.op_expr.right); - if (!l || !r) { - sema_error(sema, ref, "bad operand in bitwise"); - return 0; - } - l = underlying(sema, l); - r = underlying(sema, r); - if (l == r) { - if (!is_int_tid(sema, l)) { - sema_error(sema, ref, "bitwise requires integer operands"); - return 0; - } - return l; - } - int ll = expr_is_int_literal(sema, e->expr.op_expr.left); - int rl = expr_is_int_literal(sema, e->expr.op_expr.right); - if (ll && is_int_tid(sema, r)) - return r; - if (rl && is_int_tid(sema, l)) - return l; - sema_error(sema, ref, "type mismatch in bitwise"); - return 0; -} - -static spl_type_id_t infer_binary(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *e) { - switch (e->expr.op) { + Assert(n != NULL); + switch (n->kind) { + case SPL_AST_NONE: + case SPL_AST_CONTAINER_MEMBERS: + case SPL_AST_FN_DECL: + case SPL_AST_FN_DEFINE: + case SPL_AST_TYPE_DECL: + case SPL_AST_VAR_DECL: + case SPL_AST_CONST_DECL: + case SPL_AST_MEMBER_DECL: + case SPL_AST__COMPTIME_STMT: + case SPL_AST__DIRECTIVE_BLOCK: + case SPL_AST_PARAM_DECL: + case SPL_AST_ATTR_ITEM: + case SPL_AST_ARGG_INIT_ITEM: + case SPL_AST_IF_STATEMENT: + case SPL_AST_IFVAR_STATEMENT: + case SPL_AST_WHILE_STATEMENT: + case SPL_AST_LOOP_STATEMENT: + case SPL_AST_FOR_STATEMENT: + case SPL_AST_MATCH_STATEMENT: + case SPL_AST_RET_STATEMENT: + case SPL_AST_BREAK_STATEMENT: + case SPL_AST_CONTINUE_STATEMENT: + case SPL_AST_DEFER_STATEMENT: + case SPL_AST_TRY_STATEMENT: + case SPL_AST_CATCH_STATEMENT: + case SPL_AST_ERRDEFER_STATEMEMT: + case SPL_AST_EXPR_STATEMENT: + case SPL_AST_PACKED_EXPR: + case SPL_AST_ASSIGN_EXPR: + case SPL_AST_ASSIGN_ADD_EXPR: + case SPL_AST_ASSIGN_SUB_EXPR: + case SPL_AST_ASSIGN_MUL_EXPR: + case SPL_AST_ASSIGN_DIV_EXPR: + case SPL_AST_ASSIGN_MOD_EXPR: + case SPL_AST_ASSIGN_AND_EXPR: + case SPL_AST_ASSIGN_OR_EXPR: + case SPL_AST_ASSIGN_XOR_EXPR: + case SPL_AST_ASSIGN_LSHIFT_EXPR: + case SPL_AST_ASSIGN_USHIFT_EXPR: + case SPL_AST_BOOL_OR_EXPR: + case SPL_AST_BOOL_AND_EXPR: + case SPL_AST_BIT_OR_EXPR: + case SPL_AST_BIT_XOR_EXPR: + case SPL_AST_BIT_AND_EXPR: + case SPL_AST_CMP_EQ_EXPR: + case SPL_AST_CMP_NE_EXPR: + case SPL_AST_CMP_LE_EXPR: + case SPL_AST_CMP_GE_EXPR: + case SPL_AST_CMP_LT_EXPR: + case SPL_AST_CMP_GT_EXPR: + case SPL_AST_RANGE_EXPR: + case SPL_AST_LSHIFT_EXPR: + case SPL_AST_RSHIFT_EXPR: case SPL_AST_ADD_EXPR: case SPL_AST_SUB_EXPR: case SPL_AST_MUL_EXPR: case SPL_AST_DIV_EXPR: case SPL_AST_MOD_EXPR: - return infer_binary_arith(sema, ref, e); - case SPL_AST_CMPEQ_EXPR: - case SPL_AST_CMPNE_EXPR: - case SPL_AST_CMP_LE_EXPR: - case SPL_AST_CMP_GE_EXPR: - case SPL_AST_CMP_LT_EXPR: - case SPL_AST_CMP_GT_EXPR: - return infer_binary_cmp(sema, ref, e); - case SPL_AST_BOOLOR_EXPR: - case SPL_AST_BOOLAND_EXPR: - return infer_binary_logic(sema, ref, e); - case SPL_AST_BITOR_EXPR: - case SPL_AST_BITXOR_EXPR: - case SPL_AST_BITAND_EXPR: - case SPL_AST_LSHIFT_EXPR: - case SPL_AST_RSHIFT_EXPR: - return infer_binary_bit(sema, ref, e); - default: - return 0; - } -} - -/* 聚合初始化字面量:目标类型已知时校验字段 */ -static spl_type_id_t infer_agg_init(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - if (!pn || pn->primary_expr.kind != SPL_AST_ARGGREGATE_INIT) - return 0; - spl_type_id_t tid = 0; - if (pn->primary_expr.aggregate_init.name) { - tid = find_type(sema, pn->primary_expr.aggregate_init.name); - if (!tid) { - sema_error(sema, ref, "unknown aggregate type in literal"); - return 0; - } - } else { - /* 匿名 .{} 依赖上下文,由调用方(赋值/初始化)填充 */ - return 0; - } - spl_type_node_t *tn = type_node(sema, tid); - if (!tn || !is_agg_tid(sema, tid)) { - sema_error(sema, ref, "aggregate literal target is not a struct/union/enum"); - return 0; - } - /* 枚举无载荷初始化如 Color { .Red }:仅一个成员且为变体 */ - if (tn->kind == SPL_TYPE_ENUM) { - usize nitems = - n->kind == SPL_AST_EXPR - ? node_at(sema->ast, n->expr.op_expr.left)->primary_expr.aggregate_init.expr.size - : pn->primary_expr.aggregate_init.expr.size; - for (usize i = 0; i < nitems; i++) { - spl_ast_node_ref_t iref = - (n->kind == SPL_AST_EXPR - ? node_at(sema->ast, n->expr.op_expr.left)->primary_expr.aggregate_init.expr - : pn->primary_expr.aggregate_init.expr) - .data[i]; - spl_ast_node_t *item = node_at(sema->ast, iref); - if (!item) - continue; - spl_type_id_t mt = agg_member_type(sema, tid, item->aggregate_init_item.ident); - if (!mt) { - sema_error(sema, iref, "unknown variant in enum literal"); - continue; - } - if (item->aggregate_init_item.expr) - infer_expr(sema, item->aggregate_init_item.expr); - } - return tid; - } - /* struct/union:逐字段校验 */ - for (usize i = 0; - i < (n->kind == SPL_AST_EXPR - ? node_at(sema->ast, n->expr.op_expr.left)->primary_expr.aggregate_init.expr.size - : pn->primary_expr.aggregate_init.expr.size); - i++) { - spl_ast_node_ref_t iref = - (n->kind == SPL_AST_EXPR - ? node_at(sema->ast, n->expr.op_expr.left)->primary_expr.aggregate_init.expr - : pn->primary_expr.aggregate_init.expr) - .data[i]; - spl_ast_node_t *item = node_at(sema->ast, iref); - if (!item) - continue; - spl_type_id_t mt = agg_member_type(sema, tid, item->aggregate_init_item.ident); - if (!mt) { - sema_error(sema, iref, "unknown field in aggregate literal"); - continue; - } - if (item->aggregate_init_item.expr) { - spl_type_id_t et = infer_expr(sema, item->aggregate_init_item.expr); - int w = 0; - if (!expr_is_null_literal(sema, item->aggregate_init_item.expr) && et && - !type_compatible(sema, mt, et, - expr_is_literal(sema, item->aggregate_init_item.expr), &w)) { - sema_error(sema, iref, "field type mismatch in aggregate literal"); - } - } - } - return tid; -} - -/* 数组字面量 [N]T{...} */ -static spl_type_id_t infer_array_lit(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - spl_type_id_t elem = 0; - if (pn->primary_expr.array_lit_expr.type_expr) { - elem = resolve_type_expr(sema, pn->primary_expr.array_lit_expr.type_expr); - if (!elem) - sema_error(sema, ref, "bad array literal element type"); - } - for (usize i = 0; i < pn->primary_expr.array_lit_expr.expr_list.size; i++) { - spl_type_id_t et = infer_expr(sema, pn->primary_expr.array_lit_expr.expr_list.data[i]); - if (elem) { - int w = 0; - if (!type_compatible( - sema, elem, et, - expr_is_literal(sema, pn->primary_expr.array_lit_expr.expr_list.data[i]), &w)) { - sema_error(sema, pn->primary_expr.array_lit_expr.expr_list.data[i], - "element type mismatch in array literal"); - } - } - } - return spl_type_array(&sema->type, elem ? elem : 0, - (usize)pn->primary_expr.array_lit_expr.integer); -} - -/* 标识符:scope 查找(def → 类型) */ -static spl_type_id_t infer_ident(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - spl_def_id_t def = find_bare(sema, pn->primary_expr.ident); - spl_type_id_t t = def_type(sema, def); - if (!t) { - sema_error(sema, ref, "undefined identifier"); - return 0; - } - /* 注解:IDENT 引用 → 其符号 def(var 用 VAR、fn 用 FN_PARAMS 等) */ - pn->resolved_def_id = def; - return t; -} - -/* 表达式 ref 解析到的 def:取内层节点注解;裸 ident 兜底 find_bare */ -static spl_def_id_t expr_def_at(spl_sema_t *sema, spl_ast_node_ref_t ref) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n || n->kind != SPL_AST_EXPR) - return 0; - spl_ast_node_t *inner = node_at(sema->ast, n->expr.op_expr.left); - if (!inner) - return 0; - if (inner->resolved_def_id) - return inner->resolved_def_id; - if (n->expr.op == SPL_AST_PRIMARY_EXPR && inner->primary_expr.kind == SPL_AST_IDENT) - return find_bare(sema, inner->primary_expr.ident); - return 0; -} - -static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n); -static spl_type_id_t infer_prefix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n); -static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t ctx); - -static spl_type_id_t infer_primary(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - if (!pn) { - sema_error(sema, ref, "invalid primary expression"); - return 0; - } - switch (pn->primary_expr.kind) { - case SPL_AST_INTEGER: - return spl_type_int(&sema->type, 32, 1); - case SPL_AST_FLOAT: - return spl_type_float(&sema->type, 64); - case SPL_AST_CHAR_LIT: - /* 字符字面量即字节立即数(u8),经字面量宽化可赋给任意整数类型 */ - return spl_type_int(&sema->type, 8, 0); - case SPL_AST_STRING_LIT: - /* 字符串字面量:底层为 *u8(NUL 终止)。splc1 自举源中一律传 *u8, - * SPL.md 建议 []u8,但 IR 层按 *u8 处理,此处与实现一致 */ - return spl_type_ptr(&sema->type, spl_type_int(&sema->type, 8, 0)); - case SPL_AST_TRUE: - case SPL_AST_FALSE: - return spl_type_bool(&sema->type); - case SPL_AST_NULL: - return 0; /* null 无独立类型,需上下文 */ - case SPL_AST_IDENT: - return infer_ident(sema, ref, n); - case SPL_AST_ARGGREGATE_INIT: - return infer_agg_init(sema, ref, n); - case SPL_AST_EXPR_EXPR: - return infer_expr(sema, pn->primary_expr.expr); - case SPL_AST_ARRAY_LIT: - return infer_array_lit(sema, ref, n); - case SPL_AST_BUILTIN_EXPR: { - /* 内置调用:类型按注册表约定,参数按需推断(offsetof 字段名参数非表达式) */ - const spl_builtin_t *bi = spl_builtin_lookup(pn->primary_expr.builtin_expr.ident); - if (!bi) { - sema_error(sema, ref, "unknown builtin"); - return 0; - } - usize nargs = pn->primary_expr.builtin_expr.expr_list.size; - if (nargs < (usize)bi->min_args || (bi->max_args >= 0 && nargs > (usize)bi->max_args)) { - char buf[96]; - snprintf(buf, sizeof buf, "builtin @%s: arg count mismatch", bi->name); - sema_error(sema, ref, buf); - return 0; - } - for (usize i = 0; i < nargs; i++) { - /* offsetof 第二参数为字段标识符,不按表达式推断 */ - if (bi->kind == SPL_BUILTIN_OFFSET_OF && i == 1) - continue; - infer_expr(sema, pn->primary_expr.builtin_expr.expr_list.data[i]); - } - if (bi->ret_is_void) - return spl_type_void(&sema->type); - if (bi->kind == SPL_BUILTIN_SIZE_OF || bi->kind == SPL_BUILTIN_BITSIZE_OF || - bi->kind == SPL_BUILTIN_ALIGN_OF || bi->kind == SPL_BUILTIN_OFFSET_OF || - bi->kind == SPL_BUILTIN_FIELD_COUNT) - return spl_type_int(&sema->type, sizeof(usize) * 8, 0); - sema_error(sema, ref, "unsupported builtin"); - return 0; - } - case SPL_AST_BLOCK_EXPR: { - /* 块表达式:有独立 scope;逐语句检查,返回末尾表达式类型(无则 void) */ - spl_ast_node_ref_vec_t *items = &pn->primary_expr.block_expr; - spl_scope_id_t scope = spl_sema_scope_alloc(sema); - sema->scopes.data[scope].parent = sema->current_scope; - spl_scope_id_t save = sema->current_scope; - sema->current_scope = scope; - spl_type_id_t rt = spl_type_void(&sema->type); - spl_sema_ctx_t vctx = {0}; /* 表达式块内的 ret 暂不强制(罕见) */ - for (usize i = 0; i < items->size; i++) { - if (i + 1 == items->size) { - spl_ast_node_t *last = node_at(sema->ast, items->data[i]); - if (last && last->kind == SPL_AST_EXPR && - !(last->expr.op == SPL_AST_PRIMARY_EXPR)) { - rt = infer_expr(sema, items->data[i]); - continue; - } - if (last && last->expr.op == SPL_AST_PRIMARY_EXPR) { - spl_ast_node_t *in = node_at(sema->ast, last->expr.op_expr.left); - if (in && in->primary_expr.kind == SPL_AST_BLOCK_EXPR) { - rt = infer_primary(sema, items->data[i], last); - continue; - } - } - } - check_stmt(sema, items->data[i], vctx); - } - sema->current_scope = save; - return rt; - } - default: - return 0; - } -} - -/* 前缀运算 */ -static spl_type_id_t infer_prefix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pf = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - if (!pf) - return 0; - spl_type_id_t inner = infer_expr(sema, pf->prefix_expr.postfix_expr); - if (!inner) - return 0; - inner = underlying(sema, inner); - switch (pf->prefix_expr.kind) { case SPL_AST_MINUS_EXPR: - if (!is_numeric_tid(sema, inner)) { - sema_error(sema, ref, "unary minus requires numeric"); - return 0; - } - return inner; - case SPL_AST_BANG_EXPR: - if (inner != underlying(sema, spl_type_bool(&sema->type))) { - sema_error(sema, ref, "! requires bool"); - return 0; - } - return spl_type_bool(&sema->type); - case SPL_AST_TILDE_EXPR: - if (!is_int_tid(sema, inner)) { - sema_error(sema, ref, "~ requires integer"); - return 0; - } - return inner; - case SPL_AST_AMPERSAND_EXPR: - if (type_node(sema, inner) && type_node(sema, inner)->kind == SPL_TYPE_FN) - return inner; /* &foo 为函数值(fn 类型),非常规指针 */ - return spl_type_ptr(&sema->type, inner); - case SPL_AST_ASTERISK_EXPR: - /* 前缀 * 不在 SPL 中使用(解引用为后缀 .*),忽略 */ - return inner; - default: - return 0; - } -} - -/* 后缀运算 */ -static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *n) { - spl_ast_node_t *pf = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - if (!pf) - return 0; - spl_type_id_t base = infer_expr(sema, pf->postfix_expr.primary_expr); - if (!base) - return 0; - base = underlying(sema, base); - switch (pf->postfix_expr.kind) { - case SPL_AST_FIELD_EXPR: { - spl_type_node_t *t = type_node(sema, base); - /* 指针自动解引用一层 */ - if (t && t->kind == SPL_TYPE_PTR) - base = underlying(sema, t->ptr_pointee); - /* 注解:FIELD 节点 → 被访问聚合(自动解引用后)的 AGG def;非聚合为 0 */ - pf->resolved_def_id = def_for_type(sema, base); - t = type_node(sema, base); - if (!t) { - sema_error(sema, ref, "field access on non-aggregate"); - return 0; - } - /* 切片字段 len/ptr 优先于聚合检查 */ - if (t->kind == SPL_TYPE_SLICE) { - if (strcmp(pf->postfix_expr.field_expr, "len") == 0) - return spl_type_int(&sema->type, sizeof(usize) * 8, 0); - if (strcmp(pf->postfix_expr.field_expr, "ptr") == 0) - return spl_type_ptr(&sema->type, t->slice_element); - sema_error(sema, ref, "unknown slice field"); - return 0; - } - /* Range 内置字段 begin/end:元素类型 */ - if (t->kind == SPL_TYPE_RANGE) { - if (strcmp(pf->postfix_expr.field_expr, "begin") == 0 || - strcmp(pf->postfix_expr.field_expr, "end") == 0) - return t->range_element; - sema_error(sema, ref, "unknown range field"); - return 0; - } - if (!is_agg_tid(sema, base)) { - sema_error(sema, ref, "field access on non-aggregate"); - return 0; - } - spl_type_id_t mt = agg_member_type(sema, base, pf->postfix_expr.field_expr); - if (!mt) { - sema_error(sema, ref, "unknown field"); - return 0; - } - /* 枚举变体表达式:带载荷变体(payload 为 struct/整数)整体值为枚举类型; - * 方法(fn)/嵌套类型/无载荷固标保持 member 类型 */ - spl_type_node_t *mtt = mt ? type_node(sema, underlying(sema, mt)) : NULL; - if (t && t->kind == SPL_TYPE_ENUM && mtt && - (mtt->kind == SPL_TYPE_STRUCT || mtt->kind == SPL_TYPE_INT)) - return base; - return mt; - } - case SPL_AST_DEREF_EXPR: { - spl_type_node_t *t = type_node(sema, base); - if (!t || t->kind != SPL_TYPE_PTR) { - sema_error(sema, ref, ".* requires pointer"); - return 0; - } - /* *_(即 *void)类型已丢失,不可解引用,须先转换为具体指针 */ - spl_type_id_t pt = underlying(sema, t->ptr_pointee); - spl_type_node_t *ptn = type_node(sema, pt); - if (ptn && ptn->kind == SPL_TYPE_VOID) { - sema_error(sema, ref, "cannot dereference `*_`; cast to a concrete pointer first"); - return 0; - } - return underlying(sema, t->ptr_pointee); - } - case SPL_AST_INDEX_EXPR: { - spl_type_node_t *t = type_node(sema, base); - spl_type_id_t idx = infer_expr(sema, pf->postfix_expr.index_expr); - t = type_node(sema, base); - if (!is_int_tid(sema, underlying(sema, idx))) { - sema_error(sema, ref, "index requires integer"); - return 0; - } - if (t && t->kind == SPL_TYPE_ARRAY) - return t->array_type.element; - if (t && t->kind == SPL_TYPE_SLICE) - return t->slice_element; - if (t && t->kind == SPL_TYPE_PTR) - return underlying(sema, t->ptr_pointee); - sema_error(sema, ref, "index requires array/slice/pointer"); - return 0; - } - case SPL_AST_SLICE_EXPR: { - spl_type_node_t *t = type_node(sema, base); - if (pf->postfix_expr.slice_expr.begin) - infer_expr(sema, pf->postfix_expr.slice_expr.begin); - if (pf->postfix_expr.slice_expr.end) - infer_expr(sema, pf->postfix_expr.slice_expr.end); - t = type_node(sema, base); - if (t && t->kind == SPL_TYPE_ARRAY) - return spl_type_slice(&sema->type, t->array_type.element); - if (t && t->kind == SPL_TYPE_SLICE) - return spl_type_slice(&sema->type, t->slice_element); - sema_error(sema, ref, "slice requires array/slice"); - return 0; - } - case SPL_AST_CALL_EXPR: { - spl_type_node_t *t = type_node(sema, base); - if (!t || t->kind != SPL_TYPE_FN) { - sema_error(sema, ref, "call requires function type"); - return 0; - } - /* 注解:CALL 节点 → 被调 fn 的 def(从 callee primary 节点/裸名解析) */ - pf->resolved_def_id = expr_def_at(sema, pf->postfix_expr.primary_expr); - spl_ast_node_ref_vec_t *args = &pf->postfix_expr.call_expr; - /* 变参 fn(如 vm_printf)最后一个形参 name=NULL 且类型可为 0 */ - /* 注意:infer_expr 可能新分配类型使 type_table realloc,t 会失效,须每次刷新 */ - usize nparams = t->fn_type.params.size; - for (usize i = 0; i < args->size; i++) { - spl_type_id_t at = infer_expr(sema, args->data[i]); - t = type_node(sema, base); - if (i < nparams && t && t->fn_type.params.data[i]) { - int w = 0; - if (!expr_is_null_literal(sema, args->data[i]) && at && - !type_compatible(sema, t->fn_type.params.data[i], at, - expr_is_literal(sema, args->data[i]), &w)) { - sema_error(sema, args->data[i], "argument type mismatch"); - } - } - } - t = type_node(sema, base); - return t ? t->fn_type.ret : 0; - } - case SPL_AST_AS_EXPR: { - spl_type_id_t st = infer_expr(sema, pf->postfix_expr.primary_expr); - if (!st) - return 0; - spl_type_id_t dt = 0; - if (pf->postfix_expr.type_expr) { - /* 未知类型已由 resolve_type_atom 报错,此处不重复报"缺目标类型" */ - dt = resolve_type_expr(sema, pf->postfix_expr.type_expr); - } else { - sema_error(sema, ref, "as requires a target type"); - } - if (!dt) - return 0; - return dt; - } - default: - return 0; - } -} - -/* 表达式类型推断 */ -static spl_type_id_t infer_expr(spl_sema_t *sema, spl_ast_node_ref_t ref) { - if (!ref) - return 0; - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n) - return 0; - spl_type_id_t tid = 0; - if (n->kind == SPL_AST_EXPR) { - switch (n->expr.op) { - case SPL_AST_PRIMARY_EXPR: - tid = infer_primary(sema, ref, n); - break; - case SPL_AST_PREFIX_EXPR: - tid = infer_prefix(sema, ref, n); - break; - case SPL_AST_POSTFIX_EXPR: - tid = infer_postfix(sema, ref, n); - break; - case SPL_AST_RANGE_EXPR: { - spl_type_id_t l = 0, r = 0; - if (n->expr.op_expr.left) - l = underlying(sema, infer_expr(sema, n->expr.op_expr.left)); - if (n->expr.op_expr.right) - r = underlying(sema, infer_expr(sema, n->expr.op_expr.right)); - if ((l && !is_int_tid(sema, l)) || (r && !is_int_tid(sema, r)) || (!l && !r)) { - sema_error(sema, ref, "range bounds must be integers"); - return 0; - } - return spl_type_range(&sema->type, r ? r : l); - } - case SPL_AST_ASSIGN_EXPR: - case SPL_AST_ASSIGN_ADD_EXPR: - case SPL_AST_ASSIGN_sUB_EXPR: - case SPL_AST_ASSIGN_MUL_EXPR: - case SPL_AST_ASSIGN_DIV_EXPR: - case SPL_AST_ASSIGN_MOD_EXPR: - case SPL_AST_ASSIGN_AND_EXPR: - case SPL_AST_ASSIGN_OR_EXPR: - case SPL_AST_ASSIGN_XOR_EXPR: - case SPL_AST_ASSIGN_LSHIFT_EXPR: - case SPL_AST_ASSIGN_USHIFT_EXPR: { - spl_type_id_t l = infer_expr(sema, n->expr.op_expr.left); - spl_type_id_t r = infer_expr(sema, n->expr.op_expr.right); - if (!l || (!r && !expr_is_null_literal(sema, n->expr.op_expr.right))) { - sema_error(sema, ref, "bad assignment"); - return 0; - } - /* 不可写检查:赋值目标为 const 变量时拒绝 */ - { - spl_ast_node_t *lhs = node_at(sema->ast, n->expr.op_expr.left); - if (lhs && lhs->kind == SPL_AST_EXPR && lhs->expr.op == SPL_AST_PRIMARY_EXPR) { - spl_ast_node_t *lpn = node_at(sema->ast, lhs->expr.op_expr.left); - if (lpn && lpn->kind == SPL_AST_EXPR && - lpn->primary_expr.kind == SPL_AST_IDENT && lpn->resolved_def_id) { - spl_def_node_t *ld = def_at(sema, lpn->resolved_def_id); - if (ld && ld->kind == SPL_DEF_VAR && ld->var_def.is_const) { - sema_error(sema, ref, "cannot assign to const"); - return 0; - } - } - } - } - int w = 0; - if (!expr_is_null_literal(sema, n->expr.op_expr.right) && - !type_compatible(sema, l, r, expr_is_literal(sema, n->expr.op_expr.right), &w)) { - sema_error(sema, ref, "assignment type mismatch"); - return 0; - } - return l; - } - default: - tid = infer_binary(sema, ref, n); - break; - } - } - return tid; -} - -/* ---- 语句类型检查 ---- */ - -static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t ctx); -static void check_block(spl_sema_t *sema, spl_ast_node_ref_vec_t *block, spl_scope_id_t parent, - spl_sema_ctx_t ctx); -static spl_type_id_t infer_agg_init_with_type(spl_sema_t *sema, spl_ast_node_ref_t ref, - spl_type_id_t expect); - -/* var/const 初始化与类型注解兼容性检查;name 用于 `var x := e` 推导类型回写 */ -static void check_var_init(spl_sema_t *sema, spl_ast_node_ref_t ref, const char *name, - spl_ast_node_ref_t type_expr, spl_ast_node_ref_t init_expr, - spl_sema_ctx_t ctx) { - (void)ctx; - (void)type_expr; - /* dt 取自已登记 def 的类型(check_block 已预登记),避免二次解析重复报错 */ - spl_type_id_t dt = 0; - if (name) { - spl_scope_id_t cur = sema->current_scope; - while (cur) { - spl_def_id_t val = 0; - if (map_get(sema->scopes.data[cur].symbols, name, &val)) { - dt = def_type(sema, val); - break; - } - cur = sema->scopes.data[cur].parent; - } - } - spl_type_id_t it = 0; - if (init_expr) { - it = infer_expr(sema, init_expr); - if (!it && !expr_is_null_literal(sema, init_expr)) { - /* 匿名聚合依赖上下文类型 */ - spl_ast_node_t *in = node_at(sema->ast, init_expr); - if (in && in->kind == SPL_AST_EXPR && in->expr.op == SPL_AST_PRIMARY_EXPR) { - spl_ast_node_t *pn = node_at(sema->ast, in->expr.op_expr.left); - if (pn && pn->primary_expr.kind == SPL_AST_ARGGREGATE_INIT && dt) { - spl_type_id_t save_scope = sema->current_scope; - it = infer_agg_init_with_type(sema, init_expr, dt); - sema->current_scope = save_scope; - } - } - } - if (dt) { - int w = 0; - if (!expr_is_null_literal(sema, init_expr) && it && - !type_compatible(sema, dt, it, expr_is_literal(sema, init_expr), &w)) { - sema_error(sema, ref, "initializer type mismatch"); - } else if (w) { - sema_warn(sema, ref, "pointer conversion involves wildcard"); - } - } else if (it && name) { - /* `var x := e` 推导类型回写 binding def */ - spl_scope_id_t cur = sema->current_scope; - while (cur) { - spl_def_id_t val = 0; - if (map_get(sema->scopes.data[cur].symbols, name, &val)) { - spl_def_node_t *d = def_at(sema, val); - if (d && d->kind == SPL_DEF_VAR) { - d->type_id = it; - d->var_def.type_id = it; - } - break; - } - cur = sema->scopes.data[cur].parent; - } - } - } -} - -/* 带期望类型的匿名聚合推断 */ -static spl_type_id_t infer_agg_init_with_type(spl_sema_t *sema, spl_ast_node_ref_t ref, - spl_type_id_t expect) { - spl_ast_node_t *n = node_at(sema->ast, ref); - spl_ast_node_t *pn = n->kind == SPL_AST_EXPR ? node_at(sema->ast, n->expr.op_expr.left) : n; - if (!pn || pn->primary_expr.kind != SPL_AST_ARGGREGATE_INIT) - return 0; - spl_type_id_t tid = underlying(sema, expect); - if (!type_node(sema, tid)) - return 0; - for (usize i = 0; i < pn->primary_expr.aggregate_init.expr.size; i++) { - spl_ast_node_ref_t iref = pn->primary_expr.aggregate_init.expr.data[i]; - spl_ast_node_t *item = node_at(sema->ast, iref); - if (!item) - continue; - spl_type_node_t *tn = type_node(sema, tid); - spl_type_id_t mt = 0; - /* 切片 {} 字面量支持 .ptr/.len */ - if (tn->kind == SPL_TYPE_SLICE) { - if (strcmp(item->aggregate_init_item.ident, "ptr") == 0) - mt = spl_type_ptr(&sema->type, tn->slice_element); - else if (strcmp(item->aggregate_init_item.ident, "len") == 0) - mt = spl_type_int(&sema->type, sizeof(usize) * 8, 0); - else { - sema_error(sema, iref, "unknown field in slice literal"); - continue; - } - } else if (is_agg_tid(sema, tid)) { - mt = agg_member_type(sema, tid, item->aggregate_init_item.ident); - if (!mt) { - sema_error(sema, iref, "unknown field in aggregate literal"); - continue; - } - } else { - sema_error(sema, iref, "literal target not an aggregate"); - continue; - } - if (item->aggregate_init_item.expr) { - spl_type_id_t et = infer_expr(sema, item->aggregate_init_item.expr); - int w = 0; - if (!expr_is_null_literal(sema, item->aggregate_init_item.expr) && et && - !type_compatible(sema, mt, et, - expr_is_literal(sema, item->aggregate_init_item.expr), &w)) { - sema_error(sema, iref, "field type mismatch in aggregate literal"); - } - } - } - return tid; -} - -/* for 循环:序列类型 Range/[]T/[N]T,变量个数匹配 */ -static void check_for(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *b, - spl_sema_ctx_t ctx) { - spl_ast_node_ref_vec_t *expr_vec = &b->block_item.for_statement.expr_vec; - char **id_data = b->block_item.for_statement.ident_vec.data; - usize id_size = b->block_item.for_statement.ident_vec.size; - if (expr_vec->size != id_size) { - sema_error(sema, ref, "for: sequence/variable count mismatch"); - return; - } - spl_scope_id_t scope = spl_sema_scope_alloc(sema); - sema->scopes.data[scope].parent = sema->current_scope; - spl_scope_id_t save = sema->current_scope; - sema->current_scope = scope; - for (usize i = 0; i < expr_vec->size; i++) { - spl_type_id_t et = infer_expr(sema, expr_vec->data[i]); - et = underlying(sema, et); - spl_type_node_t *t = type_node(sema, et); - spl_type_id_t elem = 0; - if (t && t->kind == SPL_TYPE_SLICE) - elem = t->slice_element; - else if (t && t->kind == SPL_TYPE_ARRAY) - elem = t->array_type.element; - else if (t && t->kind == SPL_TYPE_RANGE) - /* Range 遍历绑定元素类型(0..n 通常为 usize 索引遍历) */ - elem = t->range_element; - else { - sema_error(sema, expr_vec->data[i], "for: sequence must be Range/[]T/[N]T"); - continue; - } - spl_def_id_t vdef = new_var_def(sema, id_data[i], elem, scope); - spl_sema_scope_insert(sema, scope, id_data[i], vdef); - } - check_block(sema, &b->block_item.for_statement.block, scope, ctx); - sema->current_scope = save; -} - -/* match:被匹配表达式须为枚举/union;臂体类型一致性本轮简化为逐臂检查 */ -static void check_match(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t *b, - spl_sema_ctx_t ctx) { - spl_type_id_t mtype = infer_expr(sema, b->block_item.match_statement.expr); - mtype = underlying(sema, mtype); - spl_type_node_t *t = type_node(sema, mtype); - /* 指针自动解引用 */ - if (t && t->kind == SPL_TYPE_PTR) - mtype = underlying(sema, t->ptr_pointee); - t = type_node(sema, mtype); - if (t && t->kind != SPL_TYPE_ENUM && t->kind != SPL_TYPE_UNION && !is_int_tid(sema, mtype)) { - sema_error(sema, b->block_item.match_statement.expr, - "match subject must be enum/union/integer"); - } - spl_ast_node_ref_vec_t *arms = &b->block_item.match_statement.paced_exprs; - spl_ast_node_ref_vec_t *bodies = &b->block_item.match_statement.match_block; - if (arms->size != bodies->size) { - sema_error(sema, ref, "match: arm pattern/body count mismatch"); - return; - } - /* 穷举检查:enum 必须覆盖所有变体,或含通配 _(含表达式的整数 match 免检) */ - { - spl_def_id_t adef = def_for_type(sema, mtype); - spl_def_node_t *ad = adef ? &sema->type.def_table.data[adef] : NULL; - int is_enum_agg = ad && ad->kind == SPL_DEF_AGG; - if (is_enum_agg) { - int has_wild = 0; - usize covered = 0; - for (usize i = 0; i < arms->size; i++) { - spl_ast_node_t *pk = node_at(sema->ast, arms->data[i]); - if (!pk) - continue; - /* _ 通配:ident 与 expr 均为空 */ - if (!pk->packed_expr.ident && !pk->packed_expr.expr) { - has_wild = 1; - break; - } - if (pk->packed_expr.ident) { - /* 变体被覆盖:匹配臂中出现的合法变体计数 */ - if (agg_member_type(sema, mtype, pk->packed_expr.ident)) - covered++; - } - } - if (!has_wild && covered < ad->agg_def.size) - sema_error(sema, ref, "match must be exhaustive"); - } - } - for (usize i = 0; i < arms->size; i++) { - spl_ast_node_t *pk = node_at(sema->ast, arms->data[i]); - if (!pk) - continue; - /* 每个臂体是 BLOCK_EXPR,有自己的 scope */ - spl_scope_id_t scope = spl_sema_scope_alloc(sema); - sema->scopes.data[scope].parent = sema->current_scope; - spl_scope_id_t save = sema->current_scope; - sema->current_scope = scope; - if (pk->packed_expr.ident) { - /* 变体模式:若带绑定则登记绑定变量 */ - if (is_agg_tid(sema, mtype) && pk->packed_expr.bind_ident) { - spl_type_id_t vt = agg_member_type(sema, mtype, pk->packed_expr.ident); - if (vt && vt != mtype) { - spl_def_id_t vdef = new_var_def(sema, pk->packed_expr.bind_ident, vt, scope); - spl_sema_scope_insert(sema, scope, pk->packed_expr.bind_ident, vdef); - } - } else if (is_agg_tid(sema, mtype)) { - if (!agg_member_type(sema, mtype, pk->packed_expr.ident)) - sema_error(sema, arms->data[i], "unknown variant in match arm"); - } - } else if (pk->packed_expr.expr) { - spl_type_id_t et = infer_expr(sema, pk->packed_expr.expr); - int w = 0; - if (is_int_tid(sema, mtype) && et && - !type_compatible(sema, mtype, et, expr_is_literal(sema, pk->packed_expr.expr), - &w)) { - sema_error(sema, pk->packed_expr.expr, "match arm pattern type mismatch"); - } - } - /* 检查臂体 */ - spl_ast_node_t *body = node_at(sema->ast, bodies->data[i]); - if (body && body->kind == SPL_AST_EXPR && body->expr.op == SPL_AST_PRIMARY_EXPR) { - spl_ast_node_t *pn = node_at(sema->ast, body->expr.op_expr.left); - if (pn && pn->primary_expr.kind == SPL_AST_BLOCK_EXPR) { - check_block(sema, &pn->primary_expr.block_expr, scope, ctx); - } else { - infer_expr(sema, bodies->data[i]); - } - } - sema->current_scope = save; - } -} - -/* 单个语句检查 */ -static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t ctx) { - spl_ast_node_t *b = node_at(sema->ast, ref); - if (!b) - return; - if (b->kind == SPL_AST_EXPR) { - /* 裸 { } 块作为语句:不产生值,仅检查其内部 */ - if (b->expr.op == SPL_AST_PRIMARY_EXPR) { - spl_ast_node_t *pn = node_at(sema->ast, b->expr.op_expr.left); - if (pn && pn->primary_expr.kind == SPL_AST_BLOCK_EXPR) { - check_block(sema, &pn->primary_expr.block_expr, sema->current_scope, ctx); - return; - } - } - infer_expr(sema, ref); - return; - } - switch (b->block_item.kind) { - case SPL_AST_VARDECL: { - spl_ast_node_t *vd = node_at(sema->ast, b->block_item.var_decl); - if (vd) - check_var_init(sema, b->block_item.var_decl, vd->var_decl.name, vd->var_decl.type_expr, - vd->var_decl.expr, ctx); + case SPL_AST_NOT_EXPR: + case SPL_AST_BIT_NOT_EXPR: + case SPL_AST_ADDRESS_EXPR: + case SPL_AST_CALL_EXPR: + case SPL_AST_FIELD_EXPR: + case SPL_AST_DEREF_EXPR: + case SPL_AST_INDEX_EXPR: + case SPL_AST_SLICE_EXPR: + case SPL_AST_AS_EXPR: + case SPL_AST_EXPR_INTEGER_LIT: + case SPL_AST_EXPR_FLOAT_LIT: + case SPL_AST_EXPR_CHAR_LIT: + case SPL_AST_EXPR_STRING_LIT: + case SPL_AST_EXPR_TRUE: + case SPL_AST_EXPR_FALSE: + case SPL_AST_EXPR_NULL: + case SPL_AST_EXPR_UNDEFINED: + case SPL_AST_EXPR_IDENT: + case SPL_AST_ARGGREGATE_INIT: + case SPL_AST_EXPR_EXPR: + case SPL_AST_ARRAY_LIT: + case SPL_AST_BUILTIN_EXPR: + case SPL_AST_BLOCK_EXPR: + case SPL_AST_BASE_TYPE_FN: + case SPL_AST_BASE_TYPE_PATH: + case SPL_AST_TYPE_POINTER: + case SPL_AST_TYPE_ARRAY: + case SPL_AST_TYPE_SLICE: + case SPL_AST_TYPE_STRUCT: + case SPL_AST_TYPE_UNION: + case SPL_AST_TYPE_SHAPE: + case SPL_AST_TYPE_ENUM: + case SPL_AST_TYPE_VOID: + case SPL_AST_TYPE_BOOL: + case SPL_AST_TYPE_OPAQUE: + case SPL_AST_TYPE_I8: + case SPL_AST_TYPE_U8: + case SPL_AST_TYPE_I16: + case SPL_AST_TYPE_U16: + case SPL_AST_TYPE_I32: + case SPL_AST_TYPE_U32: + case SPL_AST_TYPE_I64: + case SPL_AST_TYPE_U64: + case SPL_AST_TYPE_ISIZE: + case SPL_AST_TYPE_USIZE: + case SPL_AST_TYPE__F32: + case SPL_AST_TYPE__F64: + case SPL_AST_TYPE_ANY: + case SPL_AST_TYPE_IDENT: break; - } - case SPL_AST_CONSTDECL: { - spl_ast_node_t *cd = node_at(sema->ast, b->block_item.const_decl); - if (cd) - check_var_init(sema, b->block_item.const_decl, cd->const_decl.name, - cd->const_decl.type_expr, cd->const_decl.expr, ctx); - break; - } - case SPL_AST_TYPEDECL: - break; - case SPL_AST_IF_STATEMENT: { - spl_type_id_t c = infer_expr(sema, b->block_item.if_statement.expr); - c = underlying(sema, c); - if (c && c != underlying(sema, spl_type_bool(&sema->type))) - sema_error(sema, b->block_item.if_statement.expr, "if condition must be bool"); - spl_scope_id_t sc = sema->current_scope; - check_block(sema, &b->block_item.if_statement.if_block, sc, ctx); - if (b->block_item.if_statement.else_block.size) - check_block(sema, &b->block_item.if_statement.else_block, sc, ctx); - break; - } - case SPL_AST_IFVAR_STATEMENT: { - spl_ast_node_t *pk = node_at(sema->ast, b->block_item.ifvar_statement.packed_expr); - spl_type_id_t vt = 0; - if (pk && pk->packed_expr.expr) - vt = infer_expr(sema, pk->packed_expr.expr); - spl_scope_id_t sc = sema->current_scope; - if (pk && pk->packed_expr.bind_ident && vt) { - spl_scope_id_t s2 = spl_sema_scope_alloc(sema); - sema->scopes.data[s2].parent = sc; - spl_def_id_t vdef = - new_var_def(sema, pk->packed_expr.bind_ident, underlying(sema, vt), s2); - spl_sema_scope_insert(sema, s2, pk->packed_expr.bind_ident, vdef); - sema->current_scope = s2; - } - check_block(sema, &b->block_item.ifvar_statement.if_block, sema->current_scope, ctx); - sema->current_scope = sc; - if (b->block_item.ifvar_statement.else_block.size) - check_block(sema, &b->block_item.ifvar_statement.else_block, sc, ctx); - break; - } - case SPL_AST_WHILE_STATEMENT: { - spl_type_id_t c = infer_expr(sema, b->block_item.while_statement.expr); - c = underlying(sema, c); - if (c && c != underlying(sema, spl_type_bool(&sema->type))) - sema_error(sema, b->block_item.while_statement.expr, "while condition must be bool"); - check_block(sema, &b->block_item.while_statement.while_block, sema->current_scope, ctx); - break; - } - case SPL_AST_LOOP_STATEMENT: - check_block(sema, &b->block_item.loop_statement.loop_block, sema->current_scope, ctx); - break; - case SPL_AST_FOR_STATEMENT: - check_for(sema, ref, b, ctx); - break; - case SPL_AST_MATCH_STATEMENT: - check_match(sema, ref, b, ctx); - break; - case SPL_AST_RET_STATEMENT: { - spl_ast_node_t *rd = b; - if (rd->block_item.ret_statement.expr) { - spl_type_id_t et = infer_expr(sema, rd->block_item.ret_statement.expr); - if (ctx.ret) { - if (!expr_is_null_literal(sema, rd->block_item.ret_statement.expr) && et && - !type_compatible(sema, ctx.ret, et, - expr_is_literal(sema, rd->block_item.ret_statement.expr), - NULL)) { - sema_error(sema, rd->block_item.ret_statement.expr, "ret type mismatch"); - } - } - } - break; - } - case SPL_AST_BREAK_STATEMENT: - case SPL_AST_CONTINUE_STATEMENT: - break; - case SPL_AST_DEFER_STATEMENT: - check_block(sema, &b->block_item.defer_statement.block_or_statement, sema->current_scope, - ctx); - break; - case SPL_AST_EXPR_STATEMENT: - if (b->block_item.expr_statement) - infer_expr(sema, b->block_item.expr_statement); - break; - default: + case SPL_AST_COUNT: + UNREACHABLE(); break; } } -/* 块检查:为块建子 scope 并检查其中语句 */ -static void check_block(spl_sema_t *sema, spl_ast_node_ref_vec_t *block, spl_scope_id_t parent, - spl_sema_ctx_t ctx) { - spl_scope_id_t scope = spl_sema_scope_alloc(sema); - sema->scopes.data[scope].parent = parent; - spl_scope_id_t save = sema->current_scope; - sema->current_scope = scope; - /* 变量声明先登记进本块 scope,随后语句检查 */ - for (usize i = 0; i < block->size; i++) { - spl_ast_node_t *b = node_at(sema->ast, block->data[i]); - if (!b || b->kind == SPL_AST_EXPR) - continue; - if (b->block_item.kind == SPL_AST_VARDECL) { - spl_ast_node_t *vd = node_at(sema->ast, b->block_item.var_decl); - if (vd) - register_binding(sema, vd->var_decl.name, vd->var_decl.type_expr, scope, 0, - b->block_item.var_decl); - } else if (b->block_item.kind == SPL_AST_CONSTDECL) { - spl_ast_node_t *cd = node_at(sema->ast, b->block_item.const_decl); - if (cd) { - register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0, - b->block_item.const_decl); - /* 标记 const:赋值检查拒绝写入 */ - spl_ast_node_t *cn = node_at(sema->ast, b->block_item.const_decl); - if (cn && cn->resolved_def_id) { - spl_def_node_t *cdd = def_at(sema, cn->resolved_def_id); - if (cdd) - cdd->var_def.is_const = 1; - } - } - } else if (b->block_item.kind == SPL_AST_TYPEDECL) { - spl_ast_node_t *td = node_at(sema->ast, b->block_item.type_decl); - if (td) - sema_type_decl(sema, b->block_item.type_decl, scope, 0); - } - } - for (usize i = 0; i < block->size; i++) - check_stmt(sema, block->data[i], ctx); - sema->current_scope = save; +void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope) { + Assert(sema && ast && type && scope); + sema->ast = ast; + sema->type = type; + sema->scope = scope; + sema->error_count = 0; + sema->root = (spl_symbol_t){0}; } -/* 函数体检查:新建 fn_scope、登记形参(复用 def 里的 fn_params_def 类型),随后检查块 */ -static void check_fn_body(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_def_id_t fdef, - spl_scope_id_t parent_scope) { - spl_ast_node_t *n = node_at(sema->ast, ref); - if (!n || !fdef) - return; - spl_type_id_t fid = def_type(sema, fdef); - spl_type_id_t ret = 0; - spl_type_node_t *ft = type_node(sema, fid); - if (ft && ft->kind == SPL_TYPE_FN) - ret = ft->fn_type.ret; - spl_sema_ctx_t ctx = {ret}; - spl_scope_id_t fn_scope = spl_sema_scope_alloc(sema); - sema->scopes.data[fn_scope].parent = parent_scope; - spl_scope_id_t save = sema->current_scope; - sema->current_scope = fn_scope; - /* 先复制参数信息,避免 new_var_def 触发 def_table 扩容使指针失效 */ - spl_def_node_t *d = def_at(sema, fdef); - usize nparams = d ? d->fn_params_def.size : 0; - for (usize i = 0; i < nparams; i++) { - d = def_at(sema, fdef); - spl_var_def_t *pv = &d->fn_params_def.data[i]; - if (pv->name) { - spl_def_id_t pdef = new_var_def(sema, pv->name, pv->type_id, fn_scope); - spl_sema_scope_insert(sema, fn_scope, pv->name, pdef); - /* 注解:param_decl → 其在 fn_scope 的 VAR def */ - spl_ast_node_t *pd = node_at(sema->ast, n->fn_decl.param_list.data[i]); - if (pd) - pd->resolved_def_id = pdef; - } - } - check_block(sema, &n->fn_decl.block, fn_scope, ctx); - sema->current_scope = save; -} +void spl_sema_drop(spl_sema_t *sema) { (void)sema; } -void spl_sema_init(spl_sema_t *sema) { - memset(sema, 0, sizeof *sema); - spl_type_init(&sema->type); - vec_init(sema->scopes); - /* scope id 0 保留为 error */ - spl_scope_node_t s0; - memset(&s0, 0, sizeof s0); - map_init(s0.symbols, MAP_HASH_STR, MAP_CMP_STR); - vec_push(sema->scopes, s0); - sema->root_scope = spl_sema_scope_alloc(sema); - sema->current_scope = sema->root_scope; - /* 文件聚合根:$root 即文件聚合(root_def = AGG,成员为顶层声明) */ - spl_type_id_t root_type = spl_type_alloc(&sema->type); - spl_type_node_t *rn = spl_type_node(&sema->type, root_type); - rn->kind = SPL_TYPE_STRUCT; - vec_init(rn->agg_field_types); - sema->root_def = def_alloc(sema, SPL_DEF_AGG); - def_at(sema, sema->root_def)->type_id = root_type; - vec_init(def_at(sema, sema->root_def)->agg_def); - /* 关键字类型注册进 root(每个关键字一个 BUILTIN def) */ -#define SPL_REG_KEYWORD(nm, tid) \ - do { \ - spl_def_id_t _d = def_alloc(sema, SPL_DEF_BUILTIN); \ - def_at(sema, _d)->type_id = (tid); \ - spl_sema_scope_insert(sema, sema->root_scope, (nm), _d); \ - } while (0) - SPL_REG_KEYWORD("void", spl_type_void(&sema->type)); - SPL_REG_KEYWORD("bool", spl_type_bool(&sema->type)); - SPL_REG_KEYWORD("i8", spl_type_int(&sema->type, 8, 1)); - SPL_REG_KEYWORD("u8", spl_type_int(&sema->type, 8, 0)); - SPL_REG_KEYWORD("i16", spl_type_int(&sema->type, 16, 1)); - SPL_REG_KEYWORD("u16", spl_type_int(&sema->type, 16, 0)); - SPL_REG_KEYWORD("i32", spl_type_int(&sema->type, 32, 1)); - SPL_REG_KEYWORD("u32", spl_type_int(&sema->type, 32, 0)); - SPL_REG_KEYWORD("i64", spl_type_int(&sema->type, 64, 1)); - SPL_REG_KEYWORD("u64", spl_type_int(&sema->type, 64, 0)); - SPL_REG_KEYWORD("isize", spl_type_int(&sema->type, sizeof(isize) * 8, 1)); - SPL_REG_KEYWORD("usize", spl_type_int(&sema->type, sizeof(usize) * 8, 0)); - SPL_REG_KEYWORD("f32", spl_type_float(&sema->type, 32)); - SPL_REG_KEYWORD("f64", spl_type_float(&sema->type, 64)); -#undef SPL_REG_KEYWORD -} - -void spl_sema_drop(spl_sema_t *sema) { - for (usize i = 0; i < sema->scopes.size; i++) - map_free(sema->scopes.data[i].symbols); - vec_free(sema->scopes); - spl_type_drop(&sema->type); -} - -/* Pass1:预登记顶层名字,使兄弟/自引用成立(不解析成员、不检查函数体) */ void spl_sema_run(spl_sema_t *sema) { if (!sema->ast || !sema->ast->root) return; - spl_ast_node_t *c = node_at(sema->ast, sema->ast->root); - if (!c || c->kind != SPL_AST_CONTAINER_ITEM) - return; - LOG_DEBUG("sema_run root=%zu kind=%d members=%zu", sema->ast->root, c->kind, - c->container_item.members.size); - sema->current_scope = sema->root_scope; - /* 1a. 聚合壳 + 别名(类型名先全部登记,兄弟聚合可互引) */ - for (usize i = 0; i < c->container_item.members.size; i++) { - spl_ast_node_ref_t mref = c->container_item.members.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m || m->kind != SPL_AST_TYPE_DECL) + + spl_ast_node_t *ast_node = spl_ast_node(sema->ast, sema->ast->root); + Assert(ast_node != NULL && ast_node->kind == SPL_AST_CONTAINER_MEMBERS); + + // 第一趟 实现顺序无关地相互引用 + sema_collect(sema, sema->ast->root); + + // 第二趟 正式解析 + sema_parse(sema, sema->ast->root); +} + +void spl_sema_dump(spl_sema_t *sema) { + printf("Scopes:\n"); + vec_for(sema->scope->scopes, i) { + if (i == 0) continue; - spl_ast_node_t *te = node_at(sema->ast, m->type_decl.type_expr); - if (te && - (te->type_expr.kind == SPL_AST_TYPE_STRUCT || - te->type_expr.kind == SPL_AST_TYPE_UNION || te->type_expr.kind == SPL_AST_TYPE_ENUM)) { - agg_handle_t h = agg_prepare(sema, m->type_decl.type_expr); - if (!h.def) - continue; - if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, h.def)) - sema_error(sema, mref, "duplicate type name"); - agg_add_member(sema, sema->root_def, m->type_decl.name, h.tid, sema->root_scope, h.def); - } else if (te) { - spl_type_id_t tid = resolve_type_expr(sema, m->type_decl.type_expr); - spl_def_id_t def = def_alloc(sema, SPL_DEF_ALIAS); - spl_def_node_t *d = def_at(sema, def); - d->type_id = tid; - d->type_def.name = m->type_decl.name; - d->type_def.def_id = def; - d->type_def.type_id = tid; - d->type_def.scope_id = sema->root_scope; - if (!spl_sema_scope_insert(sema, sema->root_scope, m->type_decl.name, def)) - sema_error(sema, mref, "duplicate type name"); - agg_add_member(sema, sema->root_def, m->type_decl.name, tid, sema->root_scope, def); + spl_scope_node_t scope = vec_at(sema->scope->scopes, i); + printf("scope[%zu] parent=%zu\n", i, scope.parent); + map_for(scope.symbols, j) { + spl_symbol_t *symbol = &unsafe_map_at(scope.symbols, j).val; + printf(" %s -> def`%s`#%zu\n", unsafe_map_at(scope.symbols, j).key, symbol->name, + symbol->node); } } - /* 1b. fn 名(建 fn type + def) */ - for (usize i = 0; i < c->container_item.members.size; i++) { - spl_ast_node_ref_t mref = c->container_item.members.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m) - continue; - if (m->kind == SPL_AST_FN_DECL || m->kind == SPL_AST_FN_DEFINE) - sema_fn_decl(sema, mref, sema->root_scope, sema->root_def); + printf("TypeTable:\n"); + vec_for(sema->type->type_table, i) { + printf(" id#%zu type=", i); + spl_type_pure_dump(sema->type, i); + printf("\n"); } - /* 1c. 顶层 var/const */ - for (usize i = 0; i < c->container_item.members.size; i++) { - spl_ast_node_ref_t mref = c->container_item.members.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m) - continue; - if (m->kind == SPL_AST_VAR_DECL) - sema_var_decl(sema, mref, sema->root_scope, sema->root_def); - else if (m->kind == SPL_AST_CONST_DECL) - sema_const_decl(sema, mref, sema->root_scope, sema->root_def); - else if (m->kind == SPL_AST_MEMBER_DECL && m->member_decl.name) - register_binding(sema, m->member_decl.name, m->member_decl.type_expr, sema->root_scope, - sema->root_def, mref); + printf("DefTable:\n"); + vec_for(sema->type->def_table, i) { + printf(" def#%zu ", i); + spl_type_def_dump(sema->type, i); + printf("\n"); } - sema->current_scope = sema->root_scope; -} - -/* Pass2:构建聚合成员(含方法 def)并检查函数体,一次遍历完成 */ -void spl_sema_check(spl_sema_t *sema) { - if (!sema->ast || !sema->ast->root) - return; - spl_ast_node_t *c = node_at(sema->ast, sema->ast->root); - if (!c || c->kind != SPL_AST_CONTAINER_ITEM) - return; - sema->current_scope = sema->root_scope; - /* 构建所有顶层聚合成员 */ - for (usize i = 0; i < c->container_item.members.size; i++) { - spl_ast_node_ref_t mref = c->container_item.members.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m || m->kind != SPL_AST_TYPE_DECL) - continue; - spl_ast_node_t *te = node_at(sema->ast, m->type_decl.type_expr); - if (te && - (te->type_expr.kind == SPL_AST_TYPE_STRUCT || - te->type_expr.kind == SPL_AST_TYPE_UNION || te->type_expr.kind == SPL_AST_TYPE_ENUM)) { - spl_def_id_t def = find_bare(sema, m->type_decl.name); - if (!def) - continue; - agg_resolve(sema, m->type_decl.type_expr, def_type(sema, def), def, sema->root_scope, - m->type_decl.name); - } - } - /* 检查顶层函数体 */ - for (usize i = 0; i < c->container_item.members.size; i++) { - spl_ast_node_ref_t mref = c->container_item.members.data[i]; - spl_ast_node_t *m = node_at(sema->ast, mref); - if (!m || m->kind != SPL_AST_FN_DEFINE) - continue; - spl_def_id_t def = find_bare(sema, m->fn_decl.name); - check_fn_body(sema, mref, def, sema->root_scope); - } - sema->current_scope = sema->root_scope; -} - -spl_scope_id_t spl_sema_scope_alloc(spl_sema_t *sema) { - spl_scope_node_t n; - memset(&n, 0, sizeof n); - map_init(n.symbols, MAP_HASH_STR, MAP_CMP_STR); - vec_push(sema->scopes, n); - return sema->scopes.size - 1; -} - -bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name, - spl_def_id_t symbol_val) { - if (!id || id >= sema->scopes.size) - return false; - spl_def_id_t old = 0; - if (map_get(sema->scopes.data[id].symbols, symbol_name, &old)) - return false; - map_put(sema->scopes.data[id].symbols, symbol_name, symbol_val); - return true; -} - -spl_def_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path) { - if (!path.size) - return 0; - spl_def_id_t def = find_bare(sema, path.data[0]); - if (!def) - return 0; - for (usize i = 1; i < path.size; i++) { - spl_type_id_t t = def_type(sema, def); - spl_def_id_t owner = def_for_type(sema, t); - if (!owner) - return 0; - spl_def_node_t *od = def_at(sema, owner); - spl_def_id_t next = 0; - for (usize j = 0; j < od->agg_def.size; j++) { - if (od->agg_def.data[j].name && strcmp(od->agg_def.data[j].name, path.data[i]) == 0) { - next = od->agg_def.data[j].def_id ? od->agg_def.data[j].def_id - : def_for_type(sema, od->agg_def.data[j].type_id); - break; - } - } - if (!next) - return 0; - def = next; - } - return def; } diff --git a/stage1/spl_sema.h b/stage1/spl_sema.h index 2020767..ea6b76c 100644 --- a/stage1/spl_sema.h +++ b/stage1/spl_sema.h @@ -4,32 +4,51 @@ #include "spl_ast.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_def_id_t) symbols; + 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_ast_t *ast; - spl_type_t type; spl_scope_node_vec_t scopes; spl_scope_id_t root_scope; spl_scope_id_t current_scope; - spl_def_id_t root_def; +} 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); +typedef VEC(const char *) spl_symbol_path_t; +bool spl_scope_find(spl_scope_t *scop, const char *symbol_name, spl_symbol_t *out); + +typedef struct { + spl_ast_t *ast; + spl_type_t *type; + spl_scope_t *scope; + spl_symbol_t root; int error_count; } spl_sema_t; -void spl_sema_init(spl_sema_t *sema); +void spl_sema_init(spl_sema_t *sema, spl_ast_t *ast, spl_type_t *type, spl_scope_t *scope); void spl_sema_drop(spl_sema_t *sema); -void spl_sema_run(spl_sema_t *sema); -void spl_sema_check(spl_sema_t *sema); -spl_scope_id_t spl_sema_scope_alloc(spl_sema_t *sema); -bool spl_sema_scope_insert(spl_sema_t *sema, spl_scope_id_t id, const char *symbol_name, - spl_def_id_t symbol_val); -typedef VEC(const char *) spl_symbol_path_t; -spl_def_id_t spl_sema_scope_find(spl_sema_t *sema, spl_symbol_path_t path); +void spl_sema_run(spl_sema_t *sema); +void spl_sema_dump(spl_sema_t *sema); #endif /* __SPL_SEMA_H__ */ diff --git a/stage1/spl_type.c b/stage1/spl_type.c index 82af553..b3a3686 100644 --- a/stage1/spl_type.c +++ b/stage1/spl_type.c @@ -1,7 +1,48 @@ #include "spl_type.h" -static usize spl_type_hash(spl_type_node_t n) { return 0; } -static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { return 1; } +static usize spl_type_hash(spl_type_node_t n) { return n.kind; } +static int spl_type_eq(spl_type_node_t n1, spl_type_node_t n2) { + if (n1.kind != n2.kind) + return 1; + switch (n1.kind) { + case SPL_TYPE_ERROR: + case SPL_TYPE_VOID: + case SPL_TYPE_BOOL: + break; + case SPL_TYPE_INT: + if (n1.int_type.bits != n2.int_type.bits) + return 1; + if (n1.int_type.is_signed != n2.int_type.is_signed) + return 1; + break; + case SPL_TYPE_FLOAT: + if (n1.float_type.bits != n2.float_type.bits) + return 1; + break; + case SPL_TYPE_PTR: + if (n1.ptr_pointee != n2.ptr_pointee) + return 1; + break; + case SPL_TYPE_SLICE: + if (n1.slice_element != n2.slice_element) + return 1; + break; + case SPL_TYPE_RANGE: + if (n1.range_element != n2.range_element) + return 1; + break; + case SPL_TYPE_ARRAY: + if (n1.array_type.element != n2.array_type.element) + return 1; + if (n1.array_type.len != n2.array_type.len) + return 1; + break; + // TODO + default: + return 1; + } + return 0; +} spl_type_id_t spl_type_node_push(spl_type_t *type, spl_type_node_t type_node) { spl_type_id_t ret = 0; diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 1e24794..5bd8fd5 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -2,6 +2,7 @@ #define __SPL_TYPE_H__ #include "../stage0/include/utils.h" +#include "spl_dbg.h" typedef usize spl_type_id_t; /* 0 is error */ typedef VEC(spl_type_id_t) spl_type_id_vec_t; @@ -77,6 +78,7 @@ typedef struct { SPL_DEF_DISTINCT, // newtype SPL_DEF_ALIAS, // sametypes } kind; + spl_dbg_node_t dbg_node; spl_type_id_t type_id; union { spl_var_def_t var_def; diff --git a/stage1/splc0.c b/stage1/splc0.c index 2ae683d..e6abd2d 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -11,15 +11,24 @@ #include #include "spl_ast.h" -#include "spl_ast2ir.h" -#include "spl_ir2vm.h" +// #include "spl_ast2ir.h" +// #include "spl_ir2vm.h" #include "spl_lexer.h" #include "spl_sema.h" #include "spl_tok.h" +typedef enum { + DUMP_NONE, + DUMP_TOKEN, + DUMP_AST, + DUMP_SEMA, + DUMP_IR, +} dump_t; + static char *read_file(const char *path, long *out_len) { FILE *f = fopen(path, "rb"); if (!f) { + fprintf(stderr, "path `%s` ", path); perror("fopen"); return NULL; } @@ -47,8 +56,7 @@ static const char *const tok_type_names[] = { #undef X }; -static void dump_tokens(const char *src, const char *fname) { - spl_tok_vec_t toks = spl_lex(src, fname); +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]; @@ -58,170 +66,47 @@ static void dump_tokens(const char *src, const char *fname) { vec_free(toks); } -static void dump_ast(const char *src, const char *fname) { +static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug, + dump_t dump) { spl_tok_vec_t toks = spl_lex(src, fname); + if (dump == DUMP_TOKEN) { + dump_tokens(toks); + // memory leak + return 0; + } spl_ast_t ast; spl_ast_init(&ast, &toks); spl_ast_prase(&ast); if (ast.parsed < 0) { - printf("parse failed, skip AST dump\n"); - spl_ast_drop(&ast); - return; - } - spl_ast_valid(&ast); - spl_ast_dump(&ast, ast.root); - spl_ast_drop(&ast); -} - -// static void dump_sema(const char *src, const char *fname) { -// spl_tok_vec_t toks = spl_lex(src, fname); -// spl_ast_t ast; -// spl_ast_init(&ast, &toks); -// spl_ast_prase(&ast); -// if (ast.parsed < 0) { -// printf("parse failed, skip sema dump\n"); -// spl_ast_drop(&ast); -// return; -// } -// spl_ast_valid(&ast); -// spl_sema_t sema; -// spl_sema_init(&sema); -// sema.ast = * -// spl_sema_run(&sema); -// spl_sema_check(&sema); -// printf("Sema root_scope=%zu scopes=%zu errors=%d\n", sema.root_scope, sema.scopes.size, -// sema.error_count); -// for (usize i = 0; i < sema.scopes.size; i++) { -// printf("scope[%zu] parent=%zu\n", i, sema.scopes.data[i].parent); -// map_for(sema.scopes.data[i].symbols, mi) { -// printf(" %s -> def#%zu\n", sema.scopes.data[i].symbols.data[mi].key, -// sema.scopes.data[i].symbols.data[mi].val); -// } -// } -// printf("TypeTable:\n"); -// for (usize i = 0; i < sema.type.type_table.size; i++) { -// printf(" id#%zu type=", i); -// spl_type_pure_dump(&sema.type, i); -// printf("\n"); -// } -// printf("DefTable:\n"); -// for (usize i = 0; i < sema.type.def_table.size; i++) { -// printf(" def#%zu ", i); -// spl_type_def_dump(&sema.type, i); -// printf("\n"); -// } -// spl_sema_drop(&sema); -// spl_ast_drop(&ast); -// } - -// static void dump_ir(const char *src, const char *fname) { -// spl_tok_vec_t toks = spl_lex(src, fname); -// spl_ast_t ast; -// spl_ast_init(&ast, &toks); -// spl_ast_prase(&ast); -// if (ast.parsed < 0) { -// printf("parse failed, skip IR\n"); -// spl_ast_drop(&ast); -// return; -// } -// spl_ast_valid(&ast); -// spl_sema_t sema; -// spl_sema_init(&sema); -// sema.ast = * -// spl_sema_run(&sema); -// spl_sema_check(&sema); -// if (sema.error_count) { -// printf("sema errors=%d, skip IR\n", sema.error_count); -// spl_sema_drop(&sema); -// spl_ast_drop(&ast); -// return; -// } -// spl_ast2ir_t a2ir; -// spl_ast2ir_init(&a2ir, &sema); -// spl_ast2ir_run(&a2ir); -// if (a2ir.err_count) -// printf("ast2ir errors=%d\n", a2ir.err_count); -// spl_ir_dump(&a2ir.ir, &sema.type); -// spl_ast2ir_drop(&a2ir); -// spl_sema_drop(&sema); -// spl_ast_drop(&ast); -// } - -static int cmd_dump(const char *flags, const char *path) { - long len; - char *src = read_file(path, &len); - if (!src) + printf("parse failed, no output\n"); + // memory leak return 1; - int do_tokens = strstr(flags, "tokens") != NULL || strcmp(flags, "all") == 0; - int do_ast = strstr(flags, "ast") != NULL || strcmp(flags, "all") == 0; - int do_sema = strstr(flags, "sema") != NULL || strcmp(flags, "all") == 0; - int do_ir = strstr(flags, "ir") != NULL || strcmp(flags, "all") == 0; - if (do_tokens) - dump_tokens(src, path); - if (do_ast) - dump_ast(src, path); - // if (do_sema) - // dump_sema(src, path); - // if (do_ir) - // dump_ir(src, path); - free(src); - return 0; -} - -/* -g:在 .sir 尾部追加 debug 段(文本:IR 行 + VAR 行),spl_cli -g 读取 */ -static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *ir, - const spl_ir2vm_t *ir2vm) { - FILE *f = fopen(outpath, "ab"); - if (!f) - return; - fprintf(f, "SPLDBG\n"); - // for (usize i = 0; i < ir2vm->fdbg.size; i++) { - // const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i]; - // if (fd->fid >= ir->funcs.size) - // continue; - // const spl_ir_func_t *fn = &ir->funcs.data[fd->fid]; - // const char *fname = fn->name ? fn->name : "?"; - // for (usize ref = 1; ref < fd->node_first_ip.size; ref++) { - // usize ip = fd->node_first_ip.data[ref]; - // if (ip == (usize)-1) - // continue; - // const spl_ir_node_t *n = &fn->nodes.data[ref]; - // fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref), - // spl_ir_kind_name(n->kind)); - // } - // for (usize j = 0; j < fn->dbg_vars.size; j++) { - // const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j]; - // if (!dv->name) - // continue; - // fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid, - // dv->is_param); - // } - // } - fclose(f); -} - -static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug) { - // spl_tok_vec_t toks = spl_lex(src, fname); - // spl_ast_t ast; - // spl_ast_init(&ast, &toks); - // spl_ast_prase(&ast); - // if (ast.parsed < 0) { - // printf("parse failed, no output\n"); - // spl_ast_drop(&ast); - // return 1; - // } - // spl_ast_valid(&ast); - // spl_sema_t sema; - // spl_sema_init(&sema); - // sema.ast = * - // spl_sema_run(&sema); - // spl_sema_check(&sema); - // if (sema.error_count) { - // printf("sema errors=%d, no output\n", sema.error_count); - // spl_sema_drop(&sema); - // spl_ast_drop(&ast); - // return 1; - // } + } + // spl_ast_valid(&ast); TODO + if (dump == DUMP_AST) { + spl_ast_dump(&ast, ast.root); + // memory leak + return 0; + } + spl_sema_t sema; + spl_type_t type; + spl_scope_t scope; + spl_type_init(&type); + spl_scope_init(&scope); + spl_sema_init(&sema, &ast, &type, &scope); + sema.ast = * + spl_sema_run(&sema); + if (sema.error_count) { + printf("sema errors=%d, no output\n", sema.error_count); + // memory leak + return 1; + } + if (dump == DUMP_SEMA) { + spl_sema_dump(&sema); + spl_ast_dump(&ast, ast.root); + // memory leak + return 0; + } // spl_ast2ir_t a2ir; // spl_ast2ir_init(&a2ir, &sema); // spl_ast2ir_run(&a2ir); @@ -252,7 +137,7 @@ int main(int argc, char **argv) { } if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { LOG_INFO("splc0 compile (.spl -> .sir, stage B)"); - LOG_INFO("splc0 --dump dump: tokens,ast,sema,ir,all"); + LOG_INFO("splc0 --dump dump: lex,ast,sema,ir"); return 0; } int argi = 1; @@ -260,12 +145,28 @@ int main(int argc, char **argv) { LOG_FATAL("Usage: splc0 [--dump ] [out]"); return 1; } + + dump_t dump = DUMP_NONE; if (strcmp(argv[argi], "--dump") == 0) { if (argc < argi + 3) { LOG_INFO("splc0: --dump need "); return 1; } - return cmd_dump(argv[argi + 1], argv[argi + 2]); + + const char *flags = argv[argi + 1]; + if (strstr(flags, "lex") != NULL) { + dump = DUMP_TOKEN; + } + if (strstr(flags, "ast") != NULL) { + dump = DUMP_AST; + } + if (strstr(flags, "sema") != NULL) { + dump = DUMP_SEMA; + } + if (strstr(flags, "ir") != NULL) { + dump = DUMP_IR; + } + argi += 2; } /* splc0 [-g] */ if (argc < argi + 2) { @@ -285,7 +186,7 @@ int main(int argc, char **argv) { char *src = read_file(argv[argi], &len); if (!src) return 1; - int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug); + int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug, dump); free(src); return rc; }