stage1 重构测试且成功00-05

This commit is contained in:
zzy
2026-07-05 21:45:43 +08:00
parent 51d8510b79
commit e2e0ebc21f
39 changed files with 1090 additions and 461 deletions

View File

@@ -202,12 +202,14 @@ static void parse_while_stmt(spl_comp_t *ctx) {
skip_nl(ctx);
spl_parse_block(ctx);
spl_emit(ctx, SPL_JMP, SPL_VOID, loop_start);
/* JMP back to loop condition — use relative offset */
spl_val_t here = vec_size(ctx->prog.insns);
spl_emit(ctx, SPL_JMP, SPL_VOID, (spl_val_t)((isize)loop_start - (isize)here - 1));
spl_patch_to_here(ctx, bz_addr);
/* Patch any break statements */
/* Patch break statements — compute relative offset */
for (usize i = saved_bp_count; i < ctx->break_patch_count; i++) {
spl_patch(ctx, ctx->break_patches[i], vec_size(ctx->prog.insns));
spl_patch_to_here(ctx, ctx->break_patches[i]);
}
ctx->break_patch_count = saved_bp_count;
@@ -232,11 +234,13 @@ static void parse_loop_stmt(spl_comp_t *ctx) {
skip_nl(ctx);
spl_parse_block(ctx);
spl_emit(ctx, SPL_JMP, SPL_VOID, loop_start);
/* JMP back to loop start — use relative offset */
spl_val_t here = vec_size(ctx->prog.insns);
spl_emit(ctx, SPL_JMP, SPL_VOID, (spl_val_t)((isize)loop_start - (isize)here - 1));
/* Patch break statements */
/* Patch break statements — compute relative offset */
for (usize i = saved_bp_count; i < ctx->break_patch_count; i++) {
spl_patch(ctx, ctx->break_patches[i], vec_size(ctx->prog.insns));
spl_patch_to_here(ctx, ctx->break_patches[i]);
}
ctx->break_patch_count = saved_bp_count;
@@ -342,7 +346,9 @@ static void parse_continue_stmt(spl_comp_t *ctx) {
if (!ctx->in_loop) {
spl_comp_error(ctx, "continue outside loop");
}
spl_emit(ctx, SPL_JMP, SPL_VOID, ctx->continue_target);
/* Emit JMP with relative offset to continue_target */
spl_val_t here = vec_size(ctx->prog.insns);
spl_emit(ctx, SPL_JMP, SPL_VOID, (spl_val_t)((isize)ctx->continue_target - (isize)here - 1));
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
}
@@ -429,19 +435,38 @@ static void parse_extern_decl(spl_comp_t *ctx) {
* Expression statement (may include assignment)
* ============================================================ */
/* Check if token type is an assignment operator */
static int is_assign_op(spl_tok_type_t t) {
return t == TOK_ASSIGN || t == TOK_ASSIGN_ADD || t == TOK_ASSIGN_SUB ||
t == TOK_ASSIGN_MUL || t == TOK_ASSIGN_DIV || t == TOK_ASSIGN_MOD ||
t == TOK_ASSIGN_AND || t == TOK_ASSIGN_OR || t == TOK_ASSIGN_XOR ||
t == TOK_ASSIGN_L_SH || t == TOK_ASSIGN_R_SH;
}
static void parse_expr_stmt(spl_comp_t *ctx) {
/* For SPL, ret is a keyword, not an identifier.
* But the lexer might lex "return" as an ident if it's not in the keyword table.
* Let's add support for "return" as a statement as well. */
skip_nl(ctx);
if (peek(ctx)->type == KW_RET) {
parse_ret_stmt(ctx);
return;
}
int prev = ctx->tok_idx;
/* Look ahead past newlines for assignment operator */
int is_assign = 0;
if (peek(ctx)->type == TOK_IDENT) {
usize look = ctx->tok_idx + 1;
while (look < vec_size(ctx->toks) && vec_at(ctx->toks, look).type == TOK_ENDLINE)
look++;
if (look < vec_size(ctx->toks))
is_assign = is_assign_op(vec_at(ctx->toks, look).type);
}
if (is_assign) ctx->addr_of_mode = 1;
spl_expr_result_t expr = spl_parse_expr(ctx, PREC_MIN);
/* Drop the expression result if it left a value on the stack */
if (expr.type) spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
if (is_assign) ctx->addr_of_mode = 0;
if (!is_assign && expr.type) spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
/* Safety: if no token was consumed, advance to prevent infinite loop */
if (ctx->tok_idx == prev) advance(ctx);