stage1 修复类型体内部函数前向引用时 CALL 地址错误

This commit is contained in:
zzy
2026-07-12 22:16:17 +08:00
parent 1ceda90207
commit b67edc5cee
7 changed files with 273 additions and 44 deletions

View File

@@ -181,14 +181,8 @@ static void parse_method_decl(spl_comp_t *ctx, spl_type_info_t *container) {
skip_nl(ctx);
}
/* Set current_type_name for short-name resolution inside method body */
const char *saved_type_name = ctx->current_type_name;
ctx->current_type_name = container->name;
int fi = parse_fn_body(ctx, qualified, ret_type, nparams, pnames, ptypes, 0);
ctx->current_type_name = saved_type_name;
{
spl_func_info_t *f = &vec_at(ctx->funcs, fi);
f->param_types = calloc(nparams, sizeof(spl_type_info_t *));
@@ -256,6 +250,9 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
return;
advance(ctx); /* { */
/* Push type onto namespace chain for short-name resolution inside body */
spl_ns_push(ctx, container);
/* === Pass 1: Parse all nested type declarations first ===
* This allows fields/variants to reference types defined later. */
{
@@ -280,6 +277,38 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
ctx->tok_idx = saved;
}
/* === Pre-register method names for forward references === */
if (container->name) {
usize saved = ctx->tok_idx;
int depth = 1;
while (depth > 0 && ctx->tok_idx < vec_size(ctx->toks)) {
spl_tok_type_t tt = peek(ctx)->type;
if (tt == TOK_L_BRACE) {
depth++;
advance(ctx);
} else if (tt == TOK_R_BRACE) {
depth--;
if (depth == 0)
break;
advance(ctx);
} else if (tt == KW_FN && depth == 1) {
advance(ctx); /* fn */
skip_nl(ctx);
spl_tok_t *name_tok = advance(ctx);
char mname[256];
spl_tok_copy_name(name_tok, mname, sizeof(mname));
char qualified[512];
snprintf(qualified, sizeof(qualified), "%s.%s", container->name, mname);
int fi = spl_declare_func(ctx, qualified, NULL, 0, 0, 0);
/* Register in type->methods immediately so ns_chain lookup works */
spl_type_add_method(container, mname, fi);
} else {
advance(ctx);
}
}
ctx->tok_idx = saved;
}
/* === Pass 2: Parse fields/variants and methods === */
{
int depth = 1;
@@ -359,6 +388,7 @@ static void parse_type_body(spl_comp_t *ctx, spl_type_info_t *container, int is_
}
}
spl_ns_pop(ctx);
spl_type_compute_layout(container);
}
@@ -380,17 +410,25 @@ void parse_type_decl(spl_comp_t *ctx) {
expect(ctx, TOK_ASSIGN);
skip_nl(ctx);
/* Determine parent type if inside a type body (for nested type registration) */
spl_type_info_t *parent =
vec_size(ctx->ns_chain) > 0 ? vec_at(ctx->ns_chain, vec_size(ctx->ns_chain) - 1) : NULL;
if (peek(ctx)->type == KW_STRUCT) {
advance(ctx);
spl_type_info_t *st = spl_type_struct(tname);
/* Register type early to allow self-referential fields */
map_put(ctx->type_defs, strdup(tname), st);
if (parent)
map_put(parent->children, strdup(tname), st);
skip_nl(ctx);
parse_type_body(ctx, st, 0);
} else if (peek(ctx)->type == KW_UNION) {
advance(ctx);
spl_type_info_t *ut = spl_type_union(tname);
map_put(ctx->type_defs, strdup(tname), ut);
if (parent)
map_put(parent->children, strdup(tname), ut);
skip_nl(ctx);
parse_type_body(ctx, ut, 0);
} else if (peek(ctx)->type == KW_ENUM) {
@@ -398,6 +436,8 @@ void parse_type_decl(spl_comp_t *ctx) {
spl_type_info_t *et = spl_type_enum(tname);
/* Register type early to allow self-referential variants */
map_put(ctx->type_defs, strdup(tname), et);
if (parent)
map_put(parent->children, strdup(tname), et);
skip_nl(ctx);
parse_type_body(ctx, et, 1);
} else if (peek(ctx)->type == TOK_IDENT ||