stage1 重构测试且成功00-05
This commit is contained in:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user