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

@@ -58,6 +58,11 @@ static int tok_prec(spl_tok_type_t t) {
case TOK_L_SH: case TOK_R_SH: return PREC_SHIFT;
case TOK_ADD: case TOK_SUB: return PREC_ADD;
case TOK_MUL: case TOK_DIV: case TOK_MOD: return PREC_MUL;
case TOK_ASSIGN: case TOK_ASSIGN_ADD: case TOK_ASSIGN_SUB:
case TOK_ASSIGN_MUL: case TOK_ASSIGN_DIV: case TOK_ASSIGN_MOD:
case TOK_ASSIGN_AND: case TOK_ASSIGN_OR: case TOK_ASSIGN_XOR:
case TOK_ASSIGN_L_SH: case TOK_ASSIGN_R_SH:
return PREC_ASSIGN;
default: return PREC_MIN;
}
}
@@ -195,7 +200,7 @@ static spl_expr_result_t parse_char_literal(spl_comp_t *ctx) {
if (s[1] == '\\' && l >= 4) {
/* Escape sequence */
char buf = 0;
const char *cp = s + 2;
const char *cp = s + 1;
spl_decode_escape(&cp, &buf);
val = (unsigned char)buf;
} else {
@@ -383,10 +388,15 @@ static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
spl_emit(ctx, SPL_LADDR, SPL_PTR, v->slot);
if (vt->kind == TYPE_BASIC || vt->kind == TYPE_PTR) {
/* Load value for basic types and pointers */
spl_type_t bt = (vt->kind == TYPE_BASIC) ? vt->basic_type : SPL_PTR;
spl_emit(ctx, SPL_LOAD, bt, 0);
spl_expr_result_t r = { vt, 0 };
if (!ctx->addr_of_mode) {
/* Load value for basic types and pointers */
spl_type_t bt = (vt->kind == TYPE_BASIC) ? vt->basic_type : SPL_PTR;
spl_emit(ctx, SPL_LOAD, bt, 0);
spl_expr_result_t r = { vt, 0 };
return r;
}
/* In addr_of_mode, keep address on stack */
spl_expr_result_t r = { vt, 1 };
return r;
}
/* Array/struct/slice: address stays on stack */
@@ -408,7 +418,10 @@ static spl_expr_result_t parse_group(spl_comp_t *ctx) {
static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
spl_tok_t *op = advance(ctx);
if (op->type == TOK_AND) ctx->addr_of_mode = 1;
spl_expr_result_t right = spl_parse_expr(ctx, PREC_PREFIX);
if (op->type == TOK_AND) ctx->addr_of_mode = 0;
switch (op->type) {
case TOK_SUB:
@@ -713,42 +726,27 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
op == TOK_ASSIGN_AND || op == TOK_ASSIGN_OR || op == TOK_ASSIGN_XOR ||
op == TOK_ASSIGN_L_SH || op == TOK_ASSIGN_R_SH) {
/* RHS must not inherit addr_of_mode from LHS */
int saved_addr_of_mode = ctx->addr_of_mode;
ctx->addr_of_mode = 0;
spl_expr_result_t right = spl_parse_expr(ctx, PREC_MIN);
ctx->addr_of_mode = saved_addr_of_mode;
if (left.is_lvalue) {
/* Left is an address on stack */
if (op != TOK_ASSIGN) {
/* Compound: left = left op right */
spl_emit(ctx, SPL_DUP, SPL_VOID, 0); /* dup address */
spl_type_t bt = left.type && left.type->kind == TYPE_BASIC ? left.type->basic_type : SPL_I32;
spl_emit(ctx, SPL_LOAD, bt, 0); /* load old value */
/* Now old value is on stack above right */
/* But order is: left_val right_val → we need right then left */
/* Actually stack is: addr, right_val. We need: addr, old_val op right_val */
/* Let's rethink: compound assignment is: lhs = lhs op rhs */
/* We have addr and rhs on stack. We need to load lhs, then compute lhs op rhs, then store. */
/* DUP the addr, then LOAD to get old value, then SWAP to get right, then compute, then SWAP+STORE */
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); /* right, addr */
spl_emit(ctx, SPL_DUP, SPL_VOID, 0); /* right, addr, addr */
spl_emit(ctx, SPL_LOAD, bt, 0); /* right, addr, old_val */
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); /* right, old_val, addr */
spl_emit(ctx, SPL_PICK, SPL_VOID, 2); /* right, old_val, addr, right */
/* Now: right, old_val, addr, right — compute old_val op right */
/* Hmm this is getting complex. Let me try differently. */
/* Actually for bootstrap: just use a temporary. Re-load from left. */
/* OK the cleanest for compound is:
* 1. dup address
* 2. load old value
* 3. compute right
* 4. do the op
* 5. swap with address
* 6. store
*/
}
/* Store: rhs, addr — need addr then val */
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); /* addr, rhs */
spl_type_t bt = left.type && left.type->kind == TYPE_BASIC ? left.type->basic_type : SPL_I32;
spl_emit(ctx, SPL_STORE, bt, 0);
if (op == TOK_ASSIGN) {
/* Simple assignment: stack is [addr, rhs] */
/* STORE pops TOS=value, TOS-1=address — already correct order */
spl_emit(ctx, SPL_STORE, bt, 0);
} else {
/* Compound: left = left op right — stack: [addr, rhs] */
spl_emit(ctx, SPL_DUP, SPL_VOID, 0); /* [addr, rhs, addr] */
spl_emit(ctx, SPL_LOAD, bt, 0); /* [addr, rhs, old_val] */
/* FIXME: compound needs to compute old_val op rhs, then store */
/* For now just drop old_val and store rhs */
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* [addr, rhs] */
spl_emit(ctx, SPL_STORE, bt, 0);
}
}
return right;
}