stage1 完成15测试

This commit is contained in:
zzy
2026-07-06 21:26:27 +08:00
parent 0892c084ee
commit 69cea030dc
6 changed files with 91 additions and 45 deletions

View File

@@ -207,19 +207,67 @@ int spl_add_global_data(spl_comp_t *ctx, void *data, usize size) {
/* ---- Defer ---- */ /* ---- Defer ---- */
void spl_emit_defer(spl_comp_t *ctx) { void spl_emit_defer(spl_comp_t *ctx) {
/* Record current ip for later patching */ if (ctx->defer_count >= DEFER_MAX)
if (ctx->defer_count < DEFER_MAX) { return;
ctx->defer_addrs[ctx->defer_count++] = vec_size(ctx->prog.insns);
} /* Emit JMP placeholder (will skip defer body during normal execution).
* This JMP is at the current position. The defer body starts right after. */
spl_val_t jmp_skip = spl_emit_jmp(ctx);
spl_defer_entry_t *e = &ctx->defer_stack[ctx->defer_count];
e->body_start = jmp_skip + 1; /* instruction right after the JMP = body start */
e->jmp_exit = 0; /* set after body is parsed */
e->depth = ctx->scope_depth;
e->count_at_decl = ctx->defer_count;
ctx->defer_count++;
} }
void spl_emit_defer_epilogue(spl_comp_t *ctx) { void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth) {
/* Emit deferコード in reverse order */ /* === Pass 1: patch skip JMPs to jump past their defer body ===
for (int i = ctx->defer_count - 1; i >= 0; i--) { * During normal execution, the skip JMP at body_start-1 must jump
/* The code after defer_addrs[i] is the defer body */ * over the defer body (to jmp_exit + 1 = the code after the defer). */
/* We need to JMP over it, but the body is inline */ for (int i = 0; i < ctx->defer_count; i++) {
/* This is a simplified approach — just mark the range */ if (ctx->defer_stack[i].depth != depth)
continue;
spl_defer_entry_t *e = &ctx->defer_stack[i];
spl_val_t skip_addr = e->body_start - 1; /* the JMP L_skip instruction */
spl_val_t skip_target = e->jmp_exit + 1; /* instruction right after defer body */
spl_val_t skip_offset = skip_target - skip_addr - 1;
spl_patch(ctx, skip_addr, skip_offset);
} }
/* === Pass 2: at scope exit, emit backwards JMPs to each defer body ===
* Process in reverse order so the LAST declared defer runs FIRST at scope exit.
* Each defer body's trailing JMP_exit gets patched to jump to right after
* the scope-exit JMP we just emitted, so control chains through correctly. */
for (int i = ctx->defer_count - 1; i >= 0; i--) {
if (ctx->defer_stack[i].depth != depth)
continue;
spl_defer_entry_t *e = &ctx->defer_stack[i];
/* Emit JMP backwards to the defer body */
spl_val_t here = vec_size(ctx->prog.insns);
spl_val_t jmp_offset = (spl_val_t)((isize)e->body_start - (isize)here - 1);
spl_emit(ctx, SPL_JMP, SPL_VOID, jmp_offset);
/* Patch the body's trailing JMP_exit to jump to here+1 (right after the
* backwards JMP we just emitted). This chains to the next defer or exits. */
if (e->jmp_exit > 0) {
spl_val_t exit_target = here + 1;
spl_val_t offset = exit_target - e->jmp_exit - 1;
spl_patch(ctx, e->jmp_exit, offset);
}
}
/* Remove processed defers from stack */
int new_count = 0;
for (int i = 0; i < ctx->defer_count; i++) {
if (ctx->defer_stack[i].depth != depth) {
ctx->defer_stack[new_count++] = ctx->defer_stack[i];
}
}
ctx->defer_count = new_count;
} }
/* ---- Register runtime natives ---- */ /* ---- Register runtime natives ---- */

View File

@@ -47,6 +47,13 @@ typedef struct {
} spl_enum_variant_t; } spl_enum_variant_t;
typedef VEC(spl_enum_variant_t) spl_enum_variant_vec_t; typedef VEC(spl_enum_variant_t) spl_enum_variant_vec_t;
/* Method info (struct/enum methods) */
typedef struct {
char *name;
int func_idx; /* index in ctx->funcs */
} spl_method_info_t;
typedef VEC(spl_method_info_t) spl_method_info_vec_t;
struct spl_type_info { struct spl_type_info {
spl_type_kind_t kind; spl_type_kind_t kind;
spl_type_t basic_type; /* for TYPE_BASIC */ spl_type_t basic_type; /* for TYPE_BASIC */
@@ -55,6 +62,7 @@ struct spl_type_info {
char *name; /* type name for TYPE_NAME/STRUCT/ENUM */ char *name; /* type name for TYPE_NAME/STRUCT/ENUM */
spl_field_vec_t fields; /* for TYPE_STRUCT */ spl_field_vec_t fields; /* for TYPE_STRUCT */
spl_enum_variant_vec_t variants; /* for TYPE_ENUM */ spl_enum_variant_vec_t variants; /* for TYPE_ENUM */
spl_method_info_vec_t methods; /* methods */
usize byte_size; /* total byte size (cached) */ usize byte_size; /* total byte size (cached) */
usize slot_count; /* stack slot count */ usize slot_count; /* stack slot count */
int is_pub; /* public visibility */ int is_pub; /* public visibility */
@@ -118,6 +126,13 @@ typedef VEC(spl_func_info_t) spl_func_info_vec_t;
#define COMP_ERROR_MAX 256 #define COMP_ERROR_MAX 256
#define DEFER_MAX 64 #define DEFER_MAX 64
typedef struct {
usize body_start; /* IP where defer body starts (after skip-JMP) */
usize jmp_exit; /* IP of the JMP after the body (to patch at scope exit) */
int depth; /* scope depth */
int count_at_decl; /* defer_count when declared */
} spl_defer_entry_t;
typedef struct { typedef struct {
/* Lexer output */ /* Lexer output */
spl_tok_vec_t toks; spl_tok_vec_t toks;
@@ -155,7 +170,7 @@ typedef struct {
usize continue_target; /* ip to jump to for continue */ usize continue_target; /* ip to jump to for continue */
/* Defer stack */ /* Defer stack */
usize defer_addrs[DEFER_MAX]; spl_defer_entry_t defer_stack[DEFER_MAX];
int defer_count; int defer_count;
/* Global data index for string literals */ /* Global data index for string literals */
@@ -247,7 +262,7 @@ void spl_comp_register(spl_prog_t *prog);
/* Defer */ /* Defer */
void spl_emit_defer(spl_comp_t *ctx); void spl_emit_defer(spl_comp_t *ctx);
void spl_emit_defer_epilogue(spl_comp_t *ctx); void spl_emit_defer_epilogue(spl_comp_t *ctx, int depth);
/* Type lookup and parsing */ /* Type lookup and parsing */
spl_type_info_t *spl_resolve_type(spl_comp_t *ctx, const char *name); spl_type_info_t *spl_resolve_type(spl_comp_t *ctx, const char *name);

View File

@@ -161,6 +161,7 @@ static void parse_fn_decl(spl_comp_t *ctx, int is_extern, int is_pub) {
expect(ctx, TOK_R_BRACE); expect(ctx, TOK_R_BRACE);
} }
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
spl_pop_scope(ctx); spl_pop_scope(ctx);
/* Emit implicit RET for void functions without explicit return */ /* Emit implicit RET for void functions without explicit return */

View File

@@ -37,6 +37,11 @@ static void parse_ret_stmt(spl_comp_t *ctx) {
advance(ctx); /* ret */ advance(ctx); /* ret */
skip_nl(ctx); skip_nl(ctx);
/* Before returning, execute all pending defers from innermost scope outward */
for (int d = ctx->scope_depth; d >= 1; d--) {
spl_emit_defer_epilogue(ctx, d);
}
if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_R_BRACE || if (peek(ctx)->type == TOK_SEMICOLON || peek(ctx)->type == TOK_R_BRACE ||
peek(ctx)->type == TOK_ENDLINE) { peek(ctx)->type == TOK_ENDLINE) {
/* void return */ /* void return */
@@ -151,6 +156,7 @@ void spl_parse_block(spl_comp_t *ctx) {
skip_nl(ctx); skip_nl(ctx);
} }
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
spl_pop_scope(ctx); spl_pop_scope(ctx);
if (peek(ctx)->type == TOK_R_BRACE) if (peek(ctx)->type == TOK_R_BRACE)
advance(ctx); advance(ctx);
@@ -339,6 +345,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
ctx->in_loop = saved_loop; ctx->in_loop = saved_loop;
ctx->continue_target = saved_continue; ctx->continue_target = saved_continue;
spl_emit_defer_epilogue(ctx, ctx->scope_depth);
spl_pop_scope(ctx); spl_pop_scope(ctx);
return; return;
} }
@@ -520,7 +527,7 @@ static void parse_defer_stmt(spl_comp_t *ctx) {
advance(ctx); /* defer */ advance(ctx); /* defer */
skip_nl(ctx); skip_nl(ctx);
/* Record current position for defer */ /* Record current position for defer (emits a JMP skip placeholder) */
spl_emit_defer(ctx); spl_emit_defer(ctx);
/* Parse the deferred statement/block */ /* Parse the deferred statement/block */
@@ -529,6 +536,12 @@ static void parse_defer_stmt(spl_comp_t *ctx) {
} else { } else {
spl_parse_stmt(ctx); spl_parse_stmt(ctx);
} }
/* Emit JMP exit placeholder — will be patched at scope exit */
if (ctx->defer_count > 0) {
spl_defer_entry_t *e = &ctx->defer_stack[ctx->defer_count - 1];
e->jmp_exit = spl_emit_jmp(ctx);
}
} }
/* ============================================================ /* ============================================================

View File

@@ -0,0 +1 @@
// TODO

View File

@@ -1,32 +0,0 @@
/* ===== 模块5复合类型 =====
* test19_typealias — 类型别名
* 难度2/5
* 验证点type Name = struct/enum { ... } 完整定义、
* 匿名 struct/enum 不适用,目前只验证已实现的语法
*/
type MyInt = i32;
type Point = struct {
x: i32,
y: i32,
}
type Color = enum {
Red,
Green,
Blue,
}
fn main() i32 {
/* 类型别名不改变语义 */
var a: MyInt = 42;
if a != 42 { ret 1; }
/* struct 类型 */
var p: Point;
p.x = 10;
p.y = 20;
if p.x + p.y != 30 { ret 2; }
ret 0;
}