stage1 支持聚合类型方法

This commit is contained in:
zzy committed 2026-09-14 15:36:43 +08:00
1 parent 9bdb7f892e
commit 5073c2b3ea
10 files changed
+387 -148

No files matched your search

+73 -3
View File
@@ -255,6 +255,10 @@ static spl_ir_node_ref_t emit_lvalue(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
if (!spl_type_agg_member_idx(a->sema->type, agg_ir, n->field.field, &idx))
return 0;
spl_lang_type_node_t *agg_ln = spl_lang_type_node(a->sema->type, agg_lang);
if (agg_ln && agg_ln->kind == SPL_LANG_TYPE_ENUM)
idx += 1;
return spl_ir_builder_mem_field(a->ir, agg_ir, base, idx);
}
case SPL_AST_EXPR_INDEX: {
@@ -584,6 +588,18 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
if (in != SPL_INTRIN_NONE)
return ast2ir_intrin_field(a, n, in);
}
if (n->resolved_def_id) {
spl_def_node_t *fd = spl_def_node(a->sema->type, n->resolved_def_id);
if (fd && fd->kind == SPL_DEF_FN) {
spl_ir_node_ref_t fn_ref = 0;
if (!map_get(a->def2ir_map, n->resolved_def_id, &fn_ref))
return 0;
return spl_ir_builder_type_const_fn(a->ir, node_ir(a, n),
(spl_ir_func_ref_t)fn_ref);
}
}
spl_ir_node_ref_t ptr = emit_lvalue(a, ref);
if (!ptr)
return 0;
@@ -654,9 +670,40 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
spl_type_node_t *tn = spl_type_node(a->sema->type, t);
if (!tn)
Panic("aggregate type node missing");
if (tn->kind == SPL_TYPE_ENUM) {
if (vec_size(n->aggregate_literal.fields) != 1)
Panic("enum literal must have exactly one variant");
spl_ast_node_t *item =
spl_ast_node(a->sema->ast, vec_at(n->aggregate_literal.fields, 0));
if (!item || item->kind != SPL_AST_STRUCT_INIT_ITEM)
Panic("invalid enum literal");
usize vidx = 0;
if (!spl_type_agg_member_idx(a->sema->type, t, item->struct_init_item.name, &vidx))
Panic("enum variant `%s` not found (sema should have caught this)",
item->struct_init_item.name);
spl_ir_node_ref_t eptr = spl_ir_builder_mem_alloca(a->ir, t, const_usize(a, 1));
spl_type_id_t tag_ir = tn->agg_type.tag_type;
spl_ir_node_ref_t tptr =
spl_ir_builder_mem_field(a->ir, t, eptr, SPL_ENUM_TAG_FIELD_IDX);
spl_ir_node_ref_t tag_val = spl_ir_builder_type_const_int(a->ir, tag_ir, vidx);
spl_ir_builder_mem_store(a->ir, tag_ir, tptr, tag_val);
spl_type_id_t ftid = vec_at(tn->agg_type.variants, vidx).type_id;
spl_ir_node_ref_t pptr = spl_ir_builder_mem_field(a->ir, t, eptr, vidx + 1);
spl_ir_node_ref_t payload = emit_expr(a, item->struct_init_item.expr);
if (!payload)
Panic("enum payload emit failed");
spl_ir_builder_mem_store(a->ir, ftid, pptr, payload);
return eptr;
}
usize nfields = vec_size(tn->agg_type.variants);
/* 按字段名定位到 index,缺省值填 0(sema 已保证无缺省) */
spl_ir_node_ref_vec_t fields;
vec_init(fields);
for (usize i = 0; i < nfields; ++i)
@@ -694,9 +741,11 @@ static spl_ir_node_ref_t emit_expr_raw(spl_ast2ir_t *a, spl_ast_node_ref_t ref)
Panic("agg_construct failed for aggregate literal");
for (usize i = 0; i < nfields; ++i) {
spl_ir_builder_agg_construct_field(a->ir, node, vec_at(fields, i));
spl_ir_node_ref_t f = vec_at(fields, i);
if (!f)
Panic("aggregate field #%zu missing (sema should have caught this)", i);
spl_ir_builder_agg_construct_field(a->ir, node, f);
}
vec_free(fields);
return node;
}
@@ -1131,6 +1180,21 @@ static void emit_fn(spl_ast2ir_t *a, spl_ast_node_t *n) {
spl_ir_builder_fn_end(a->ir);
}
static void emit_aggregate_fns(spl_ast2ir_t *a, spl_ast_node_t *te) {
for (usize i = 0; i < vec_size(te->type_aggregate.members); ++i) {
spl_ast_node_t *mn = spl_ast_node(a->sema->ast, vec_at(te->type_aggregate.members, i));
if (!mn)
continue;
if (mn->kind == SPL_AST_FN_DECL) {
emit_fn(a, mn);
} else if (mn->kind == SPL_AST_MEMBER_DECL && mn->member_decl.type_expr) {
spl_ast_node_t *mt = spl_ast_node(a->sema->ast, mn->member_decl.type_expr);
if (mt && mt->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns(a, mt);
}
}
}
static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
spl_ast_node_t *n = spl_ast_node(a->sema->ast, ref);
if (!n)
@@ -1152,6 +1216,12 @@ static void emit_container(spl_ast2ir_t *a, spl_ast_node_ref_t ref) {
case SPL_AST_FN_DECL:
emit_fn(a, d);
break;
case SPL_AST_TYPE_DECL: {
spl_ast_node_t *te = spl_ast_node(a->sema->ast, d->type_decl.type_expr);
if (te && te->kind == SPL_AST_TYPE_AGGREGATE)
emit_aggregate_fns(a, te);
break;
}
case SPL_AST_TOP_LEVEL_BLOCK:
emit_container(a, dref);
break;