stage2 修复语义问题

This commit is contained in:
zzy committed 2026-10-08 22:46:31 +08:00
1 parent 76f980654c
commit fc2d8f8db4
2 files changed
+74 -28

No files matched your search

+36 -16
View File
@@ -302,27 +302,23 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
spl_lang_type_id_t saved_agg = sema->current_aggregate_lang;
sema->current_aggregate_lang = agg_lang;
/* 聚合体自成命名空间:成员类型可引用同体声明的嵌套类型(裸名)。 */
sema_push_scope(sema);
spl_type_member_vec_t members;
vec_init(members);
spl_lang_method_vec_t methods;
vec_init(methods);
/* 第一遍:登记嵌套类型/函数的 def,挂进 methods 与聚合作用域。成员类型可能引用它们,
必须早于成员类型推断,否则限定名(经 methods)与裸名(经作用域)都解析不到。 */
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
spl_ast_node_t *mn = spl_ast_node(sema->ast, mref);
if (!mn)
continue;
if (mn->kind == SPL_AST_MEMBER_DECL) {
spl_lang_type_id_t mtid = 0;
if (mn->member_decl.type_expr)
mtid = sema_infer(sema, mn->member_decl.type_expr);
spl_type_member_t m = {.name = mn->member_decl.name,
.type_id = spl_lang_type_get_ir_type(sema->type, mtid),
.ast_node_ref = mref};
vec_push(members, m);
} else if (mn->kind == SPL_AST_FN_DECL) {
if (mn->kind == SPL_AST_FN_DECL) {
spl_def_id_t fn_def = mn->resolved_def_id;
if (!fn_def) {
fn_def = spl_def_alloc(sema->type, SPL_DEF_FN, mn->fn_decl.name, mn->dbg, sema->ast,
@@ -334,6 +330,9 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
fn_d->owner_def = owner_def_id;
spl_lang_method_t meth = {.name = mn->fn_decl.name, .def_id = fn_def};
vec_push(methods, meth);
spl_symbol_t fsym = {.name = mn->fn_decl.name, .kind = SPL_SYMBOL_KIND_FN};
fsym.node = fn_def;
spl_scope_insert(sema->scope, sema->scope->current_scope, fsym);
} else if (mn->kind == SPL_AST_TYPE_DECL) {
spl_ast_node_t *tpat = spl_ast_node(sema->ast, mn->type_decl.pattern);
if (!tpat || tpat->kind != SPL_AST_PATTERN_IDENT)
@@ -352,9 +351,37 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
}
spl_lang_method_t meth = {.name = tname, .def_id = tdef};
vec_push(methods, meth);
spl_symbol_t tsym = {.name = tname, .kind = SPL_SYMBOL_KIND_TYPE};
tsym.node = tdef;
spl_scope_insert(sema->scope, sema->scope->current_scope, tsym);
}
}
spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang);
if (lslot) {
vec_free(lslot->methods);
lslot->methods = methods;
vec_init(methods);
}
/* 第二遍:成员(字段/变体)类型推断;此时嵌套名字已可解析。 */
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_ref_t mref = vec_at(te->type_aggregate.members, i);
spl_ast_node_t *mn = spl_ast_node(sema->ast, mref);
if (!mn)
continue;
if (mn->kind == SPL_AST_MEMBER_DECL) {
spl_lang_type_id_t mtid = 0;
if (mn->member_decl.type_expr)
mtid = sema_infer(sema, mn->member_decl.type_expr);
spl_type_member_t m = {.name = mn->member_decl.name,
.type_id = spl_lang_type_get_ir_type(sema->type, mtid),
.ast_node_ref = mref};
vec_push(members, m);
}
}
sema_pop_scope(sema);
sema->current_aggregate_lang = saved_agg;
spl_type_node_t tn = {0};
@@ -366,13 +393,6 @@ static spl_lang_type_id_t sema_build_aggregate(spl_sema_t *sema, spl_ast_node_t
vec_init(members);
spl_lang_define_ir(sema->type, agg_ir, &tn);
spl_lang_type_node_t *lslot = spl_lang_type_node(sema->type, agg_lang);
if (lslot) {
vec_free(lslot->methods);
lslot->methods = methods;
vec_init(methods);
}
return agg_lang;
}
+38 -12
View File
@@ -367,6 +367,10 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
var saved = self.current_aggregate_lang;
self.current_aggregate_lang = agg_lang;
// 聚合体自成命名空间:成员类型可引用同体声明的嵌套类型(裸名)。
var saved_scope = self.scope.current_scope;
var agg_scope = Scope.alloc(&self.scope);
self.scope.current_scope = agg_scope;
var members = Vec.blank(@sizeof(Member), @alignof(Member));
var methods = Vec.blank(@sizeof(LangMethod), @alignof(LangMethod));
@@ -376,19 +380,15 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
.TypeAggregate(&x) => { mlist = x.members; },
_ => {},
}
// 第一遍:登记嵌套类型/函数的 def,挂进 methods 与聚合作用域。成员类型可能引用它们,
// 必须早于成员类型推断,否则限定名(经 methods)与裸名(经作用域)都解析不到。
var i: usize = 0;
while i < mlist.len {
var mref = list_at(mlist, i);
var mn = node(self, mref);
if mn != null {
match mn.body {
.MemberDecl(md) => {
var mtid: usize = 0;
if md.type_expr != 0 { mtid = infer(self, md.type_expr); }
var mm = Member { .name = md.name, .type_id = ir_of(self, mtid),
.ast_node_ref = mref };
Vec.push(&members, &mm as *u8);
},
.FnDecl(fd) => {
var fn_def = mn.resolved_def_id;
if fn_def == 0 {
@@ -400,6 +400,8 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
if fn_d != null { fn_d.owner_def = owner_def_id; }
var meth = LangMethod { .name = fd.name, .def_id = fn_def };
Vec.push(&methods, &meth as *u8);
Scope.insert(&self.scope, agg_scope,
Symbol { .name = fd.name, .kind = .Fn, .node = fn_def });
},
.TypeDecl(td) => {
var tpat = node(self, td.pattern);
@@ -416,6 +418,8 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
}
var meth = LangMethod { .name = tname, .def_id = tdef };
Vec.push(&methods, &meth as *u8);
Scope.insert(&self.scope, agg_scope,
Symbol { .name = tname, .kind = .Type, .node = tdef });
}
},
_ => {},
@@ -424,6 +428,33 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
i = i + 1;
}
var lslot = LangType.lang_node(&self.types, agg_lang);
if lslot != null {
Vec.drop(&lslot.methods);
lslot.methods = methods;
}
// 第二遍:成员(字段/变体)类型推断;此时嵌套名字已可解析。
i = 0;
while i < mlist.len {
var mref = list_at(mlist, i);
var mn = node(self, mref);
if mn != null {
match mn.body {
.MemberDecl(md) => {
var mtid: usize = 0;
if md.type_expr != 0 { mtid = infer(self, md.type_expr); }
var mm = Member { .name = md.name, .type_id = ir_of(self, mtid),
.ast_node_ref = mref };
Vec.push(&members, &mm as *u8);
},
_ => {},
}
}
i = i + 1;
}
self.scope.current_scope = saved_scope;
self.current_aggregate_lang = saved;
// IR 节点
@@ -445,11 +476,6 @@ fn build_aggregate(self: *Sema, te: *Node, owner_def_id: usize): usize {
}
TypeTable.define(&self.types.ir, agg_ir, &tk);
var lslot = LangType.lang_node(&self.types, agg_lang);
if lslot != null {
Vec.drop(&lslot.methods);
lslot.methods = methods;
}
ret agg_lang;
}