stage1 完成15测试
This commit is contained in:
@@ -207,20 +207,68 @@ 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, int depth) {
|
||||||
|
/* === Pass 1: patch skip JMPs to jump past their defer body ===
|
||||||
|
* During normal execution, the skip JMP at body_start-1 must jump
|
||||||
|
* over the defer body (to jmp_exit + 1 = the code after the defer). */
|
||||||
|
for (int i = 0; i < ctx->defer_count; i++) {
|
||||||
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void spl_emit_defer_epilogue(spl_comp_t *ctx) {
|
/* Remove processed defers from stack */
|
||||||
/* Emit deferコード in reverse order */
|
int new_count = 0;
|
||||||
for (int i = ctx->defer_count - 1; i >= 0; i--) {
|
for (int i = 0; i < ctx->defer_count; i++) {
|
||||||
/* The code after defer_addrs[i] is the defer body */
|
if (ctx->defer_stack[i].depth != depth) {
|
||||||
/* We need to JMP over it, but the body is inline */
|
ctx->defer_stack[new_count++] = ctx->defer_stack[i];
|
||||||
/* This is a simplified approach — just mark the range */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ctx->defer_count = new_count;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Register runtime natives ---- */
|
/* ---- Register runtime natives ---- */
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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 */
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
|
|||||||
1
stage1/test19_mutiarray.spl
Normal file
1
stage1/test19_mutiarray.spl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
// TODO
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user