stage1 支持聚合类型方法
This commit is contained in:
1 parent
9bdb7f892e
commit
5073c2b3ea
10 files changed
+387
-148
No files matched your search
+73
-3
@@ -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;
|
||||
|
||||
Reference in new issue
Block a user