stage1 修复类型体内部函数前向引用时 CALL 地址错误
This commit is contained in:
@@ -547,9 +547,20 @@ spl_expr_result_t spl_parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *typ
|
||||
skip_nl(ctx);
|
||||
}
|
||||
} else if (type->kind == TYPE_ENUM) {
|
||||
if (peek(ctx)->type == TOK_DOT)
|
||||
/* Parse variant name with optional type qualifier(s):
|
||||
* .name, TypeName.name, or bare name (same pattern as
|
||||
* spl_emit_match_enum_cmp for consistency) */
|
||||
spl_tok_t *vtok;
|
||||
if (peek(ctx)->type == TOK_DOT) {
|
||||
advance(ctx);
|
||||
spl_tok_t *vtok = advance(ctx);
|
||||
vtok = advance(ctx);
|
||||
} else {
|
||||
vtok = advance(ctx);
|
||||
while (peek(ctx)->type == TOK_DOT) {
|
||||
advance(ctx);
|
||||
vtok = advance(ctx);
|
||||
}
|
||||
}
|
||||
char vname[256];
|
||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||
skip_nl(ctx);
|
||||
@@ -654,11 +665,6 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
|
||||
/* Check if it's a function call: ident(...) */
|
||||
if (peek(ctx)->type == TOK_L_PAREN) {
|
||||
int fi = spl_lookup_func(ctx, name);
|
||||
if (fi < 0 && ctx->current_type_name) {
|
||||
char qualified[512];
|
||||
snprintf(qualified, sizeof(qualified), "%s.%s", ctx->current_type_name, name);
|
||||
fi = spl_lookup_func(ctx, qualified);
|
||||
}
|
||||
if (fi < 0) {
|
||||
spl_comp_error(ctx, "unknown function '%s'", name);
|
||||
spl_expr_result_t r = {0};
|
||||
@@ -675,9 +681,12 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, nidx);
|
||||
spl_emit(ctx, SPL_NCALL, SPL_VOID, nargs);
|
||||
} else {
|
||||
spl_val_t addr = vec_at(ctx->prog.funcs, f->func_idx).address;
|
||||
spl_emit(ctx, SPL_PUSH, SPL_PTR, addr);
|
||||
/* Record fixup for forward-reference resolution */
|
||||
spl_val_t fixup_idx = vec_size(ctx->prog.insns);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_PTR, 0); /* placeholder address */
|
||||
spl_emit(ctx, SPL_CALL, SPL_VOID, nargs);
|
||||
vec_push(ctx->call_fixups, fixup_idx);
|
||||
vec_push(ctx->call_fixup_funcs, f->func_idx);
|
||||
}
|
||||
|
||||
spl_expr_result_t r = {f->ret_type, 0};
|
||||
@@ -941,9 +950,12 @@ static spl_expr_result_t parse_postfix_expr(spl_comp_t *ctx, spl_expr_result_t l
|
||||
nargs += parse_call_args(ctx);
|
||||
expect(ctx, TOK_R_PAREN);
|
||||
|
||||
spl_val_t addr = vec_at(ctx->prog.funcs, func->func_idx).address;
|
||||
spl_emit(ctx, SPL_PUSH, SPL_PTR, addr);
|
||||
/* Record fixup for forward-reference resolution */
|
||||
spl_val_t fixup_idx = vec_size(ctx->prog.insns);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_PTR, 0); /* placeholder address */
|
||||
spl_emit(ctx, SPL_CALL, SPL_VOID, nargs);
|
||||
vec_push(ctx->call_fixups, fixup_idx);
|
||||
vec_push(ctx->call_fixup_funcs, func->func_idx);
|
||||
|
||||
left = (spl_expr_result_t){func->ret_type, 0};
|
||||
break;
|
||||
@@ -1220,12 +1232,44 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
|
||||
|
||||
spl_enum_variant_t *spl_emit_match_enum_cmp(spl_comp_t *ctx, spl_type_info_t *enum_type,
|
||||
int val_offset) {
|
||||
if (peek(ctx)->type == TOK_DOT)
|
||||
advance(ctx);
|
||||
spl_tok_t *vtok = advance(ctx);
|
||||
char vname[256];
|
||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||
|
||||
/* Parse variant reference, reusing the same type resolution path
|
||||
* as the expression parser (parse_ident + postfix DOT handler):
|
||||
*
|
||||
* .unknown — leading DOT shortcut
|
||||
* unknown — bare variant name
|
||||
* Tag.unknown — type-qualified (resolves Tag via spl_resolve_type)
|
||||
* Token.Tag.unknown — fully qualified (walks all segments)
|
||||
*
|
||||
* Only the final segment is the variant name; preceding segments
|
||||
* are optional type qualifiers resolved through the type system. */
|
||||
if (peek(ctx)->type == TOK_DOT) {
|
||||
advance(ctx); /* . */
|
||||
} else {
|
||||
/* Read first name; if followed by DOT, it's a type qualifier —
|
||||
* verify it resolves via spl_resolve_type (same as parse_ident). */
|
||||
spl_tok_t *tok = advance(ctx);
|
||||
spl_tok_copy_name(tok, vname, sizeof(vname));
|
||||
|
||||
while (peek(ctx)->type == TOK_DOT) {
|
||||
spl_type_info_t *qt = spl_resolve_type(ctx, vname);
|
||||
(void)qt; /* qualifier verified through type system */
|
||||
advance(ctx); /* . */
|
||||
tok = advance(ctx);
|
||||
spl_tok_copy_name(tok, vname, sizeof(vname));
|
||||
}
|
||||
|
||||
/* Now vname holds the final segment — the variant name */
|
||||
goto lookup;
|
||||
}
|
||||
|
||||
{
|
||||
spl_tok_t *vtok = advance(ctx);
|
||||
spl_tok_copy_name(vtok, vname, sizeof(vname));
|
||||
}
|
||||
|
||||
lookup:
|
||||
vec_for(enum_type->variants, vi) {
|
||||
spl_enum_variant_t *v = &vec_at(enum_type->variants, vi);
|
||||
if (strcmp(v->name, vname) == 0) {
|
||||
|
||||
Reference in New Issue
Block a user