stage1 修复类型体内部函数前向引用时 CALL 地址错误
This commit is contained in:
@@ -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 ||
|
||||
|
||||
Reference in New Issue
Block a user