stage1 实现06测试
This commit is contained in:
@@ -1,33 +1,39 @@
|
||||
/* spl_stmt.c — Statement parser + codegen */
|
||||
|
||||
#include "spl_comp.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
static spl_tok_t *peek(spl_comp_t *ctx) {
|
||||
return &vec_at(ctx->toks, ctx->tok_idx);
|
||||
}
|
||||
static spl_tok_t *peek(spl_comp_t *ctx) { return &vec_at(ctx->toks, ctx->tok_idx); }
|
||||
|
||||
static spl_tok_t *advance(spl_comp_t *ctx) {
|
||||
spl_tok_t *t = &vec_at(ctx->toks, ctx->tok_idx);
|
||||
if (t->type != TOK_EOF) ctx->tok_idx++;
|
||||
if (t->type != TOK_EOF)
|
||||
ctx->tok_idx++;
|
||||
return t;
|
||||
}
|
||||
|
||||
static int expect(spl_comp_t *ctx, spl_tok_type_t type) {
|
||||
if (peek(ctx)->type == type) { advance(ctx); return 1; }
|
||||
spl_comp_error(ctx, "expected '%s', got '%s'", spl_tok_type_name(type), spl_tok_type_name(peek(ctx)->type));
|
||||
if (peek(ctx)->type == type) {
|
||||
advance(ctx);
|
||||
return 1;
|
||||
}
|
||||
spl_comp_error(ctx, "expected '%s', got '%s'", spl_tok_type_name(type),
|
||||
spl_tok_type_name(peek(ctx)->type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int match(spl_comp_t *ctx, spl_tok_type_t type) {
|
||||
if (peek(ctx)->type == type) { advance(ctx); return 1; }
|
||||
if (peek(ctx)->type == type) {
|
||||
advance(ctx);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void skip_nl(spl_comp_t *ctx) {
|
||||
while (peek(ctx)->type == TOK_ENDLINE) advance(ctx);
|
||||
while (peek(ctx)->type == TOK_ENDLINE)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -48,7 +54,8 @@ static void parse_ret_stmt(spl_comp_t *ctx) {
|
||||
spl_type_t rt = ctx->current_ret_type ? ctx->current_ret_type->basic_type : SPL_VOID;
|
||||
spl_emit(ctx, SPL_RET, rt, 0);
|
||||
}
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -62,7 +69,8 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
||||
spl_tok_t *name_tok = advance(ctx);
|
||||
char vname[256];
|
||||
usize nlen = name_tok->len < 255 ? name_tok->len : 255;
|
||||
memcpy(vname, name_tok->lexeme, nlen); vname[nlen] = '\0';
|
||||
memcpy(vname, name_tok->lexeme, nlen);
|
||||
vname[nlen] = '\0';
|
||||
|
||||
spl_type_info_t *var_type = NULL;
|
||||
int has_init = 0;
|
||||
@@ -84,12 +92,15 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
||||
|
||||
if (peek(ctx)->type == TOK_COLON_ASSIGN || peek(ctx)->type == TOK_ASSIGN) {
|
||||
has_init = 1;
|
||||
if (peek(ctx)->type == TOK_COLON_ASSIGN) advance(ctx);
|
||||
else advance(ctx); /* = */
|
||||
if (peek(ctx)->type == TOK_COLON_ASSIGN)
|
||||
advance(ctx);
|
||||
else
|
||||
advance(ctx); /* = */
|
||||
}
|
||||
|
||||
/* Allocate stack slot */
|
||||
if (!var_type) var_type = spl_type_basic(SPL_I32); /* default type */
|
||||
if (!var_type)
|
||||
var_type = spl_type_basic(SPL_I32); /* default type */
|
||||
int slot = spl_declare_var(ctx, vname, var_type, is_const);
|
||||
|
||||
skip_nl(ctx);
|
||||
@@ -126,7 +137,8 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
||||
}
|
||||
}
|
||||
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -145,7 +157,8 @@ void spl_parse_block(spl_comp_t *ctx) {
|
||||
}
|
||||
|
||||
spl_pop_scope(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACE) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACE)
|
||||
advance(ctx);
|
||||
} else {
|
||||
/* Single statement */
|
||||
spl_parse_stmt(ctx);
|
||||
@@ -257,68 +270,218 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
||||
skip_nl(ctx);
|
||||
|
||||
/* Parse the iteration expression(s) */
|
||||
spl_expr_result_t start = spl_parse_expr(ctx, PREC_MIN);
|
||||
(void)start;
|
||||
spl_expr_result_t start_expr = spl_parse_expr(ctx, PREC_MIN);
|
||||
|
||||
if (peek(ctx)->type == TOK_RANGE) {
|
||||
/* for begin..end as i { body } */
|
||||
advance(ctx); /* .. */
|
||||
spl_expr_result_t end = spl_parse_expr(ctx, PREC_MIN);
|
||||
(void)end;
|
||||
/* ===== Numeric range: for begin..end as i { body } ===== */
|
||||
advance(ctx); /* .. */
|
||||
spl_parse_expr(ctx, PREC_MIN); /* end expression */
|
||||
/* Stack: [begin, end] */
|
||||
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == KW_AS) {
|
||||
advance(ctx); /* as */
|
||||
spl_tok_t *ivar = advance(ctx);
|
||||
char iname[256];
|
||||
usize inl = ivar->len < 255 ? ivar->len : 255;
|
||||
memcpy(iname, ivar->lexeme, inl); iname[inl] = '\0';
|
||||
|
||||
/* Declare loop variable */
|
||||
spl_type_info_t *itype = spl_type_basic(SPL_I32);
|
||||
int islot = spl_declare_var(ctx, iname, itype, 0);
|
||||
|
||||
/* The loop variable was already set up by the range operator */
|
||||
/* Store initial value */
|
||||
/* For now: we need to emit proper loop code. This is a simplification. */
|
||||
int saved_loop = ctx->in_loop;
|
||||
usize saved_continue = ctx->continue_target;
|
||||
usize saved_bp_count = ctx->break_patch_count;
|
||||
|
||||
ctx->in_loop = 1;
|
||||
ctx->continue_target = 0; /* will set after store */
|
||||
|
||||
/* Loop: store begin to i, check i < end, body, i++ */
|
||||
/* Stack has: begin, end (from parsing the range expression) */
|
||||
/* Actually we need to emit proper code here. For bootstrap,
|
||||
let me just handle the simple numeric for loop. */
|
||||
|
||||
/* For now, emit a basic loop body */
|
||||
if (peek(ctx)->type != KW_AS) {
|
||||
skip_nl(ctx);
|
||||
spl_parse_block(ctx);
|
||||
return;
|
||||
}
|
||||
advance(ctx); /* as */
|
||||
|
||||
spl_tok_t *ivar = advance(ctx);
|
||||
char iname[256];
|
||||
usize inl = ivar->len < 255 ? ivar->len : 255;
|
||||
memcpy(iname, ivar->lexeme, inl);
|
||||
iname[inl] = '\0';
|
||||
|
||||
spl_push_scope(ctx);
|
||||
int islot = spl_declare_var(ctx, iname, spl_type_basic(SPL_I32), 0);
|
||||
|
||||
/* Stack: [begin, end]; swap so TOS = begin */
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
/* Store begin to i */
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||
/* Stack: [end] */
|
||||
|
||||
spl_val_t loop_start = vec_size(ctx->prog.insns);
|
||||
|
||||
/* Condition: i < end */
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
|
||||
spl_emit(ctx, SPL_SLT, SPL_I32, 0);
|
||||
spl_val_t bz_addr = spl_emit_bz(ctx);
|
||||
|
||||
int saved_loop = ctx->in_loop;
|
||||
usize saved_continue = ctx->continue_target;
|
||||
usize saved_bp_count = ctx->break_patch_count;
|
||||
ctx->in_loop = 1;
|
||||
ctx->continue_target = loop_start;
|
||||
|
||||
ctx->in_loop = saved_loop;
|
||||
ctx->continue_target = saved_continue;
|
||||
ctx->break_patch_count = saved_bp_count;
|
||||
}
|
||||
} else if (peek(ctx)->type == TOK_COMMA) {
|
||||
/* for slice, 0.. as val, idx { body } — skip for now */
|
||||
advance(ctx); /* , */
|
||||
spl_parse_expr(ctx, PREC_MIN); /* skip the range */
|
||||
if (peek(ctx)->type == KW_AS) {
|
||||
advance(ctx);
|
||||
advance(ctx); /* val */
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
advance(ctx); /* idx */
|
||||
}
|
||||
}
|
||||
skip_nl(ctx);
|
||||
spl_parse_block(ctx);
|
||||
} else {
|
||||
/* for ident in ... — skip */
|
||||
skip_nl(ctx);
|
||||
spl_parse_block(ctx);
|
||||
spl_parse_block(ctx); /* body */
|
||||
|
||||
/* Increment: i = i + 1 */
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, 1);
|
||||
spl_emit(ctx, SPL_ADD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||
|
||||
/* JMP back to condition */
|
||||
spl_val_t jmp_here = vec_size(ctx->prog.insns);
|
||||
spl_emit(ctx, SPL_JMP, SPL_VOID, (spl_val_t)((isize)loop_start - (isize)jmp_here - 1));
|
||||
|
||||
/* Exit: patch bz, drop end */
|
||||
spl_patch_to_here(ctx, bz_addr);
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
||||
|
||||
/* Patch breaks */
|
||||
for (usize i = saved_bp_count; i < ctx->break_patch_count; i++)
|
||||
spl_patch_to_here(ctx, ctx->break_patches[i]);
|
||||
ctx->break_patch_count = saved_bp_count;
|
||||
ctx->in_loop = saved_loop;
|
||||
ctx->continue_target = saved_continue;
|
||||
|
||||
spl_pop_scope(ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ===== Slice iteration: for slice [as val |, range as val, idx] ===== */
|
||||
int has_idx = 0;
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx); /* , */
|
||||
spl_parse_expr(ctx, PREC_MIN); /* parse start of range (e.g. 0) */
|
||||
if (peek(ctx)->type == TOK_RANGE) {
|
||||
advance(ctx); /* .. */
|
||||
/* consume optional end expression */
|
||||
if (peek(ctx)->type != KW_AS && peek(ctx)->type != TOK_COMMA &&
|
||||
peek(ctx)->type != TOK_L_BRACE && peek(ctx)->type != TOK_ENDLINE &&
|
||||
peek(ctx)->type != TOK_EOF)
|
||||
spl_parse_expr(ctx, PREC_MIN);
|
||||
}
|
||||
has_idx = 1;
|
||||
/* Range pushed a value; we manage our own idx, drop it */
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
||||
}
|
||||
|
||||
if (peek(ctx)->type != KW_AS) {
|
||||
skip_nl(ctx);
|
||||
spl_parse_block(ctx);
|
||||
return;
|
||||
}
|
||||
advance(ctx); /* as */
|
||||
|
||||
/* Parse val variable name */
|
||||
spl_tok_t *vtok = advance(ctx);
|
||||
char vname[256];
|
||||
usize vnl = vtok->len < 255 ? vtok->len : 255;
|
||||
memcpy(vname, vtok->lexeme, vnl);
|
||||
vname[vnl] = '\0';
|
||||
|
||||
/* Parse optional idx variable name */
|
||||
char iname[256] = {0};
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
spl_tok_t *itok = advance(ctx);
|
||||
usize inl = itok->len < 255 ? itok->len : 255;
|
||||
memcpy(iname, itok->lexeme, inl);
|
||||
iname[inl] = '\0';
|
||||
}
|
||||
|
||||
/* Stack: [slice_addr] or whatever the slice expression left */
|
||||
spl_push_scope(ctx);
|
||||
|
||||
int idx_slot = -1;
|
||||
if (iname[0])
|
||||
idx_slot = spl_declare_var(ctx, iname, spl_type_basic(SPL_I32), 0);
|
||||
|
||||
spl_type_info_t *elem_type = NULL;
|
||||
if (start_expr.type) {
|
||||
if (start_expr.type->kind == TYPE_SLICE)
|
||||
elem_type = start_expr.type->elem;
|
||||
else if (start_expr.type->kind == TYPE_PTR && start_expr.type->elem)
|
||||
elem_type = start_expr.type->elem;
|
||||
}
|
||||
if (!elem_type)
|
||||
elem_type = spl_type_basic(SPL_I32);
|
||||
int val_slot = spl_declare_var(ctx, vname, elem_type, 0);
|
||||
|
||||
/* Extract ptr and len from slice, push index=0: stack [ptr, len, idx] */
|
||||
spl_emit(ctx, SPL_DUP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
|
||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, 0);
|
||||
/* Stack: [ptr, len, idx=0] */
|
||||
|
||||
spl_val_t loop_start = vec_size(ctx->prog.insns);
|
||||
|
||||
/* Condition: idx < len */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy len */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy idx */
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); /* [idx, len] → [len, idx] → SWAP → [idx, len] */
|
||||
spl_emit(ctx, SPL_SLT, SPL_I32, 0);
|
||||
spl_val_t bz_addr = spl_emit_bz(ctx);
|
||||
|
||||
/* Store current idx to idx variable */
|
||||
if (idx_slot >= 0) {
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx (TOS) */
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, idx_slot);
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||
}
|
||||
|
||||
/* Load slice[idx] and store to val */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 2); /* copy ptr: [ptr, len, idx, ptr] */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy idx: [ptr, len, idx, ptr, idx] */
|
||||
usize elem_byte_size = (elem_type && elem_type->byte_size) ? elem_type->byte_size : 4;
|
||||
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
|
||||
spl_emit(ctx, SPL_MUL, SPL_U64, 0);
|
||||
spl_emit(ctx, SPL_ADD, SPL_U64, 0);
|
||||
spl_emit(ctx, SPL_LOAD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_LADDR, SPL_PTR, val_slot);
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_STORE, SPL_I32, 0);
|
||||
|
||||
/* Loop context */
|
||||
int saved_loop = ctx->in_loop;
|
||||
usize saved_continue = ctx->continue_target;
|
||||
usize saved_bp_count = ctx->break_patch_count;
|
||||
ctx->in_loop = 1;
|
||||
ctx->continue_target = loop_start;
|
||||
|
||||
skip_nl(ctx);
|
||||
spl_parse_block(ctx); /* body */
|
||||
|
||||
/* Increment idx */
|
||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx */
|
||||
spl_emit(ctx, SPL_PUSH, SPL_I32, 1);
|
||||
spl_emit(ctx, SPL_ADD, SPL_I32, 0);
|
||||
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* replace old idx with new */
|
||||
|
||||
/* JMP back to condition */
|
||||
spl_val_t jmp_here = vec_size(ctx->prog.insns);
|
||||
spl_emit(ctx, SPL_JMP, SPL_VOID, (spl_val_t)((isize)loop_start - (isize)jmp_here - 1));
|
||||
|
||||
/* Exit: patch bz, drop idx, len, ptr */
|
||||
spl_patch_to_here(ctx, bz_addr);
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* drop idx */
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* drop len */
|
||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* drop ptr */
|
||||
|
||||
/* Patch breaks */
|
||||
for (usize i = saved_bp_count; i < ctx->break_patch_count; i++)
|
||||
spl_patch_to_here(ctx, ctx->break_patches[i]);
|
||||
ctx->break_patch_count = saved_bp_count;
|
||||
ctx->in_loop = saved_loop;
|
||||
ctx->continue_target = saved_continue;
|
||||
|
||||
spl_pop_scope(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -338,7 +501,8 @@ static void parse_break_stmt(spl_comp_t *ctx) {
|
||||
ctx->break_patch_cap = new_cap;
|
||||
}
|
||||
ctx->break_patches[ctx->break_patch_count++] = addr;
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
static void parse_continue_stmt(spl_comp_t *ctx) {
|
||||
@@ -349,7 +513,8 @@ static void parse_continue_stmt(spl_comp_t *ctx) {
|
||||
/* 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);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -379,8 +544,10 @@ static void parse_extern_decl(spl_comp_t *ctx) {
|
||||
advance(ctx); /* # */
|
||||
expect(ctx, TOK_L_BRACKET);
|
||||
/* Skip extern("vm") or just look for fn */
|
||||
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACKET) advance(ctx);
|
||||
while (peek(ctx)->type != TOK_R_BRACKET && peek(ctx)->type != TOK_EOF)
|
||||
advance(ctx);
|
||||
if (peek(ctx)->type == TOK_R_BRACKET)
|
||||
advance(ctx);
|
||||
|
||||
skip_nl(ctx);
|
||||
|
||||
@@ -390,7 +557,8 @@ static void parse_extern_decl(spl_comp_t *ctx) {
|
||||
spl_tok_t *fname_tok = advance(ctx);
|
||||
char fn_name[256];
|
||||
usize fnl = fname_tok->len < 255 ? fname_tok->len : 255;
|
||||
memcpy(fn_name, fname_tok->lexeme, fnl); fn_name[fnl] = '\0';
|
||||
memcpy(fn_name, fname_tok->lexeme, fnl);
|
||||
fn_name[fnl] = '\0';
|
||||
|
||||
skip_nl(ctx);
|
||||
expect(ctx, TOK_L_PAREN);
|
||||
@@ -409,8 +577,15 @@ static void parse_extern_decl(spl_comp_t *ctx) {
|
||||
}
|
||||
nparams++;
|
||||
skip_nl(ctx);
|
||||
if (peek(ctx)->type == TOK_COMMA) { advance(ctx); skip_nl(ctx); continue; }
|
||||
if (peek(ctx)->type == TOK_ELLIPSIS) { advance(ctx); skip_nl(ctx); } /* variadic */
|
||||
if (peek(ctx)->type == TOK_COMMA) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
continue;
|
||||
}
|
||||
if (peek(ctx)->type == TOK_ELLIPSIS) {
|
||||
advance(ctx);
|
||||
skip_nl(ctx);
|
||||
} /* variadic */
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -421,13 +596,15 @@ static void parse_extern_decl(spl_comp_t *ctx) {
|
||||
spl_type_info_t *ret_type = spl_type_basic(SPL_VOID);
|
||||
if (peek(ctx)->type != TOK_SEMICOLON && peek(ctx)->type != TOK_L_BRACE) {
|
||||
ret_type = spl_parse_type(ctx);
|
||||
if (!ret_type) ret_type = spl_type_basic(SPL_VOID);
|
||||
if (!ret_type)
|
||||
ret_type = spl_type_basic(SPL_VOID);
|
||||
skip_nl(ctx);
|
||||
}
|
||||
|
||||
spl_declare_func(ctx, fn_name, ret_type, nparams, 1, 0);
|
||||
|
||||
if (peek(ctx)->type == TOK_SEMICOLON) advance(ctx);
|
||||
if (peek(ctx)->type == TOK_SEMICOLON)
|
||||
advance(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,10 +614,10 @@ static void parse_extern_decl(spl_comp_t *ctx) {
|
||||
|
||||
/* 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;
|
||||
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) {
|
||||
@@ -462,14 +639,19 @@ static void parse_expr_stmt(spl_comp_t *ctx) {
|
||||
is_assign = is_assign_op(vec_at(ctx->toks, look).type);
|
||||
}
|
||||
|
||||
if (is_assign) ctx->addr_of_mode = 1;
|
||||
if (is_assign)
|
||||
ctx->addr_of_mode = 1;
|
||||
spl_expr_result_t expr = spl_parse_expr(ctx, PREC_MIN);
|
||||
if (is_assign) ctx->addr_of_mode = 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);
|
||||
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);
|
||||
if (ctx->tok_idx == prev)
|
||||
advance(ctx);
|
||||
}
|
||||
|
||||
/* ============================================================
|
||||
@@ -479,7 +661,8 @@ static void parse_expr_stmt(spl_comp_t *ctx) {
|
||||
void spl_parse_stmt(spl_comp_t *ctx) {
|
||||
skip_nl(ctx);
|
||||
|
||||
if (peek(ctx)->type == TOK_EOF || peek(ctx)->type == TOK_R_BRACE) return;
|
||||
if (peek(ctx)->type == TOK_EOF || peek(ctx)->type == TOK_R_BRACE)
|
||||
return;
|
||||
|
||||
switch (peek(ctx)->type) {
|
||||
case KW_RET:
|
||||
@@ -521,7 +704,7 @@ void spl_parse_stmt(spl_comp_t *ctx) {
|
||||
case TOK_LINE_COMMENT:
|
||||
advance(ctx);
|
||||
break;
|
||||
case TOK_SHARP: /* #[extern(...)] */
|
||||
case TOK_SHARP: /* #[extern(...)] */
|
||||
parse_extern_decl(ctx);
|
||||
break;
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user