stage1 重构到 USIZE, 使得 vm 支持 usize, isize

This commit is contained in:
zzy
2026-07-06 00:07:39 +08:00
parent 67c8a137dd
commit 5dadf6d6ee
3 changed files with 121 additions and 59 deletions

View File

@@ -140,6 +140,8 @@ static int spl_type_size(spl_type_t t) {
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_USIZE: \
case SPL_ISIZE: \
_r = _a OP _b; \ _r = _a OP _b; \
break; \ break; \
default: \ default: \
@@ -199,6 +201,8 @@ static int spl_type_size(spl_type_t t) {
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_USIZE: \
case SPL_ISIZE: \
_r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \ _r = (spl_val_t)((int64_t)_a OP(int64_t) _b); \
break; \ break; \
default: \ default: \
@@ -238,6 +242,8 @@ static int spl_type_size(spl_type_t t) {
_r = (spl_val_t)((uint64_t)_a OP(uint64_t) _b); \ _r = (spl_val_t)((uint64_t)_a OP(uint64_t) _b); \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_USIZE: \
case SPL_ISIZE: \
_r = _a OP _b; \ _r = _a OP _b; \
break; \ break; \
default: \ default: \
@@ -274,6 +280,8 @@ static int spl_type_size(spl_type_t t) {
_r = (int64_t)_a OP(int64_t) _b; \ _r = (int64_t)_a OP(int64_t) _b; \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_USIZE: \
case SPL_ISIZE: \
_r = _a OP _b; \ _r = _a OP _b; \
break; \ break; \
case SPL_F32: { \ case SPL_F32: { \
@@ -325,7 +333,9 @@ static int spl_type_size(spl_type_t t) {
_r = (int64_t)_a OP(int64_t) _b; \ _r = (int64_t)_a OP(int64_t) _b; \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
_r = (int64_t)_a OP(int64_t) _b; \ case SPL_USIZE: \
case SPL_ISIZE: \
_r = _a OP _b; \
break; \ break; \
case SPL_F32: { \ case SPL_F32: { \
float _fa, _fb; \ float _fa, _fb; \
@@ -376,6 +386,8 @@ static int spl_type_size(spl_type_t t) {
_r = (uint64_t)_a OP(uint64_t) _b; \ _r = (uint64_t)_a OP(uint64_t) _b; \
break; \ break; \
case SPL_U64: \ case SPL_U64: \
case SPL_USIZE: \
case SPL_ISIZE: \
_r = _a OP _b; \ _r = _a OP _b; \
break; \ break; \
default: \ default: \

View File

@@ -97,7 +97,7 @@ static void emit_slice_create(spl_comp_t *ctx, usize stride) {
/* --- Compute len = end - begin --- */ /* --- Compute len = end - begin --- */
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* [base, begin, end, ptr, end] */ spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* [base, begin, end, ptr, end] */
spl_emit(ctx, SPL_PICK, SPL_VOID, 3); /* [base, begin, end, ptr, end, begin] */ spl_emit(ctx, SPL_PICK, SPL_VOID, 3); /* [base, begin, end, ptr, end, begin] */
spl_emit(ctx, SPL_SUB, SPL_I32, 0); /* [base, begin, end, ptr, len] */ spl_emit(ctx, SPL_SUB, SPL_USIZE, 0); /* [base, begin, end, ptr, len] */
/* --- Cleanup: drop [base, begin, end], keep [ptr, len] --- */ /* --- Cleanup: drop [base, begin, end], keep [ptr, len] --- */
spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [base, begin, ptr, len, end] */ spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [base, begin, ptr, len, end] */
@@ -442,10 +442,25 @@ static spl_expr_result_t parse_prefix_op(spl_comp_t *ctx) {
} }
break; break;
case TOK_MUL: case TOK_MUL:
/* *expr — dereference: push the pointer value, then load */ /* *expr — dereference */
/* right should evaluate to the pointer */
if (right.type && right.type->kind == TYPE_PTR && right.type->elem) { if (right.type && right.type->kind == TYPE_PTR && right.type->elem) {
spl_emit(ctx, SPL_LOAD, right.type->elem->basic_type, 0); /* If right is still an lvalue, load the pointer value for the target */
if (right.is_lvalue) {
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
}
spl_type_info_t *elem = right.type->elem;
if (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR) {
if (!ctx->addr_of_mode) {
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
spl_emit(ctx, SPL_LOAD, bt, 0);
right = (spl_expr_result_t){ elem, 0 };
} else {
right = (spl_expr_result_t){ elem, 1 };
}
} else {
/* Struct/array/slice: keep address on stack */
right = (spl_expr_result_t){ elem, 1 };
}
} }
break; break;
default: default:
@@ -544,15 +559,19 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
if (strcmp(vec_at(left.type->fields, fi).name, fname) == 0) { if (strcmp(vec_at(left.type->fields, fi).name, fname) == 0) {
spl_field_t *f = &vec_at(left.type->fields, fi); spl_field_t *f = &vec_at(left.type->fields, fi);
if (f->offset > 0) { if (f->offset > 0) {
spl_emit(ctx, SPL_PUSH, SPL_I32, f->offset); spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
spl_emit(ctx, SPL_ADD, SPL_I32, 0); spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
} }
/* Load value if basic type */ /* Load value if basic type */
spl_type_info_t *ft = f->type; spl_type_info_t *ft = f->type;
if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) { if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) {
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR; if (!ctx->addr_of_mode) {
spl_emit(ctx, SPL_LOAD, bt, 0); spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
left = (spl_expr_result_t){ ft, 0 }; spl_emit(ctx, SPL_LOAD, bt, 0);
left = (spl_expr_result_t){ ft, 0 };
} else {
left = (spl_expr_result_t){ ft, 1 };
}
} else { } else {
left = (spl_expr_result_t){ ft, 1 }; left = (spl_expr_result_t){ ft, 1 };
} }
@@ -566,21 +585,27 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
if (left.type && left.type->kind == TYPE_PTR && left.type->elem && if (left.type && left.type->kind == TYPE_PTR && left.type->elem &&
left.type->elem->kind == TYPE_STRUCT) { left.type->elem->kind == TYPE_STRUCT) {
spl_type_info_t *st = left.type->elem; spl_type_info_t *st = left.type->elem;
/* Left has the pointer value on stack. Load it to get the struct address. */ /* Load pointer value to get struct address if left is still lvalue */
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0); if (left.is_lvalue) {
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
}
/* Now search field */ /* Now search field */
vec_for(st->fields, fi) { vec_for(st->fields, fi) {
if (strcmp(vec_at(st->fields, fi).name, fname) == 0) { if (strcmp(vec_at(st->fields, fi).name, fname) == 0) {
spl_field_t *f = &vec_at(st->fields, fi); spl_field_t *f = &vec_at(st->fields, fi);
if (f->offset > 0) { if (f->offset > 0) {
spl_emit(ctx, SPL_PUSH, SPL_I32, f->offset); spl_emit(ctx, SPL_PUSH, SPL_USIZE, f->offset);
spl_emit(ctx, SPL_ADD, SPL_I32, 0); spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
} }
spl_type_info_t *ft = f->type; spl_type_info_t *ft = f->type;
if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) { if (ft->kind == TYPE_BASIC || ft->kind == TYPE_PTR) {
spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR; if (!ctx->addr_of_mode) {
spl_emit(ctx, SPL_LOAD, bt, 0); spl_type_t bt = (ft->kind == TYPE_BASIC) ? ft->basic_type : SPL_PTR;
left = (spl_expr_result_t){ ft, 0 }; spl_emit(ctx, SPL_LOAD, bt, 0);
left = (spl_expr_result_t){ ft, 0 };
} else {
left = (spl_expr_result_t){ ft, 1 };
}
} else { } else {
left = (spl_expr_result_t){ ft, 1 }; left = (spl_expr_result_t){ ft, 1 };
} }
@@ -596,8 +621,8 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
/* Slice: 2 slots [ptr, len]. len is at offset sizeof(spl_val_t) */ /* Slice: 2 slots [ptr, len]. len is at offset sizeof(spl_val_t) */
spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t)); spl_emit(ctx, SPL_PUSH, SPL_U64, (spl_val_t)sizeof(spl_val_t));
spl_emit(ctx, SPL_ADD, SPL_U64, 0); spl_emit(ctx, SPL_ADD, SPL_U64, 0);
spl_emit(ctx, SPL_LOAD, SPL_I32, 0); spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
left = (spl_expr_result_t){ spl_type_basic(SPL_I32), 0 }; left = (spl_expr_result_t){ spl_type_basic(SPL_USIZE), 0 };
} else if (strcmp(fname, "ptr") == 0) { } else if (strcmp(fname, "ptr") == 0) {
/* ptr is at offset 0 */ /* ptr is at offset 0 */
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0); spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
@@ -606,22 +631,30 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
continue; continue;
} }
/* Postfix dereference: expr.* */
if (strcmp(fname, "*") == 0 && left.type && left.type->kind == TYPE_PTR && left.type->elem) {
if (left.is_lvalue) {
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
}
spl_type_info_t *elem = left.type->elem;
if (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR) {
if (!ctx->addr_of_mode) {
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
spl_emit(ctx, SPL_LOAD, bt, 0);
left = (spl_expr_result_t){ elem, 0 };
} else {
left = (spl_expr_result_t){ elem, 1 };
}
} else {
left = (spl_expr_result_t){ elem, 1 };
}
continue;
}
spl_comp_error(ctx, "unknown field '%s'", fname); spl_comp_error(ctx, "unknown field '%s'", fname);
continue; continue;
} }
/* Postfix deref: expr.* */
if (opt == TOK_MUL && ctx->tok_idx + 1 < vec_size(ctx->toks) &&
peek(ctx)->type == TOK_MUL && vec_at(ctx->toks, ctx->tok_idx + 1).type == TOK_MUL) {
/* Handle .* — actually just * (multiplication) */
/* The spec defines .* as postfix deref, but in token stream,
* the lexer tokenizes .* as TOK_DOT + TOK_MUL */
/* Actually, .* is not a multi-char token. Let's check the lexer. */
/* If we see . then *, it's field access then multiplication? No. */
/* In .*, we see TOK_DOT then TOK_MUL. But after TOK_DOT we already consumed
* the next token as a field name. So .* doesn't work with the current approach. */
}
/* Array/slice indexing: expr[expr] or expr[begin..end] */ /* Array/slice indexing: expr[expr] or expr[begin..end] */
if (opt == TOK_L_BRACKET) { if (opt == TOK_L_BRACKET) {
advance(ctx); /* skip [ */ advance(ctx); /* skip [ */
@@ -654,7 +687,7 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t)); spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
spl_emit(ctx, SPL_ADD, SPL_U64, 0); spl_emit(ctx, SPL_ADD, SPL_U64, 0);
spl_emit(ctx, SPL_LOAD, SPL_I32, 0); spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
} }
} }
@@ -695,9 +728,13 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
spl_emit(ctx, SPL_ADD, SPL_U64, 0); spl_emit(ctx, SPL_ADD, SPL_U64, 0);
} }
if (elem && (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR)) { if (elem && (elem->kind == TYPE_BASIC || elem->kind == TYPE_PTR)) {
spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR; if (!ctx->addr_of_mode) {
spl_emit(ctx, SPL_LOAD, bt, 0); spl_type_t bt = (elem->kind == TYPE_BASIC) ? elem->basic_type : SPL_PTR;
left = (spl_expr_result_t){ elem, 0 }; spl_emit(ctx, SPL_LOAD, bt, 0);
left = (spl_expr_result_t){ elem, 0 };
} else {
left = (spl_expr_result_t){ elem, 1 };
}
} else { } else {
left = (spl_expr_result_t){ elem, 1 }; left = (spl_expr_result_t){ elem, 1 };
} }
@@ -752,7 +789,9 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
ctx->addr_of_mode = saved_addr_of_mode; ctx->addr_of_mode = saved_addr_of_mode;
if (left.is_lvalue) { if (left.is_lvalue) {
spl_type_t bt = left.type && left.type->kind == TYPE_BASIC ? left.type->basic_type : SPL_I32; spl_type_t bt = left.type ?
(left.type->kind == TYPE_BASIC ? left.type->basic_type :
left.type->kind == TYPE_PTR ? SPL_PTR : SPL_I32) : SPL_I32;
if (op == TOK_ASSIGN) { if (op == TOK_ASSIGN) {
/* Simple assignment: stack is [addr, rhs] */ /* Simple assignment: stack is [addr, rhs] */
/* STORE pops TOS=value, TOS-1=address — already correct order */ /* STORE pops TOS=value, TOS-1=address — already correct order */

View File

@@ -124,14 +124,16 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
* Store len at slot+1, then ptr at slot. */ * Store len at slot+1, then ptr at slot. */
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot + 1); spl_emit(ctx, SPL_LADDR, SPL_PTR, slot + 1);
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_STORE, SPL_I32, 0); spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot); spl_emit(ctx, SPL_LADDR, SPL_PTR, slot);
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_STORE, SPL_PTR, 0); spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
} else { } else {
/* Single value store */ /* Single value store */
spl_emit(ctx, SPL_LADDR, SPL_PTR, slot); spl_emit(ctx, SPL_LADDR, SPL_PTR, slot);
spl_type_t bt = var_type->kind == TYPE_BASIC ? var_type->basic_type : SPL_I32; spl_type_t bt = (var_type->kind == TYPE_BASIC) ? var_type->basic_type
: (var_type->kind == TYPE_PTR) ? SPL_PTR
: SPL_I32;
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_STORE, bt, 0); spl_emit(ctx, SPL_STORE, bt, 0);
} }
@@ -293,23 +295,23 @@ static void parse_for_stmt(spl_comp_t *ctx) {
iname[inl] = '\0'; iname[inl] = '\0';
spl_push_scope(ctx); spl_push_scope(ctx);
int islot = spl_declare_var(ctx, iname, spl_type_basic(SPL_I32), 0); int islot = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
/* Stack: [begin, end]; swap so TOS = begin */ /* Stack: [begin, end]; swap so TOS = begin */
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
/* Store begin to i */ /* Store begin to i */
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot); spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_STORE, SPL_I32, 0); spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
/* Stack: [end] */ /* Stack: [end] */
spl_val_t loop_start = vec_size(ctx->prog.insns); spl_val_t loop_start = vec_size(ctx->prog.insns);
/* Condition: i < end */ /* Condition: i < end */
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_LOAD, SPL_USIZE, 0);
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); spl_emit(ctx, SPL_PICK, SPL_VOID, 1);
spl_emit(ctx, SPL_SLT, SPL_I32, 0); spl_emit(ctx, SPL_ULT, SPL_USIZE, 0);
spl_val_t bz_addr = spl_emit_bz(ctx); spl_val_t bz_addr = spl_emit_bz(ctx);
int saved_loop = ctx->in_loop; int saved_loop = ctx->in_loop;
@@ -324,10 +326,10 @@ static void parse_for_stmt(spl_comp_t *ctx) {
/* Increment: i = i + 1 */ /* Increment: i = i + 1 */
spl_emit(ctx, SPL_LADDR, SPL_PTR, islot); spl_emit(ctx, SPL_LADDR, SPL_PTR, islot);
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_LOAD, SPL_USIZE, 0);
spl_emit(ctx, SPL_PUSH, SPL_I32, 1); spl_emit(ctx, SPL_PUSH, SPL_USIZE, 1);
spl_emit(ctx, SPL_ADD, SPL_I32, 0); spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
spl_emit(ctx, SPL_STORE, SPL_I32, 0); spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
/* JMP back to condition */ /* JMP back to condition */
spl_val_t jmp_here = vec_size(ctx->prog.insns); spl_val_t jmp_here = vec_size(ctx->prog.insns);
@@ -395,7 +397,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
int idx_slot = -1; int idx_slot = -1;
if (iname[0]) if (iname[0])
idx_slot = spl_declare_var(ctx, iname, spl_type_basic(SPL_I32), 0); idx_slot = spl_declare_var(ctx, iname, spl_type_basic(SPL_USIZE), 0);
spl_type_info_t *elem_type = NULL; spl_type_info_t *elem_type = NULL;
if (start_expr.type) { if (start_expr.type) {
@@ -414,8 +416,8 @@ static void parse_for_stmt(spl_comp_t *ctx) {
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t)); spl_emit(ctx, SPL_PUSH, SPL_U64, sizeof(spl_val_t));
spl_emit(ctx, SPL_ADD, SPL_U64, 0); spl_emit(ctx, SPL_ADD, SPL_U64, 0);
spl_emit(ctx, SPL_LOAD, SPL_I32, 0); spl_emit(ctx, SPL_LOAD, SPL_USIZE, 0);
spl_emit(ctx, SPL_PUSH, SPL_I32, 0); spl_emit(ctx, SPL_PUSH, SPL_USIZE, 0);
/* Stack: [ptr, len, idx=0] */ /* Stack: [ptr, len, idx=0] */
spl_val_t loop_start = vec_size(ctx->prog.insns); spl_val_t loop_start = vec_size(ctx->prog.insns);
@@ -424,7 +426,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* copy 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_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_SWAP, SPL_VOID, 0); /* [idx, len] → [len, idx] → SWAP → [idx, len] */
spl_emit(ctx, SPL_SLT, SPL_I32, 0); spl_emit(ctx, SPL_ULT, SPL_USIZE, 0);
spl_val_t bz_addr = spl_emit_bz(ctx); spl_val_t bz_addr = spl_emit_bz(ctx);
/* Store current idx to idx variable */ /* Store current idx to idx variable */
@@ -432,7 +434,7 @@ static void parse_for_stmt(spl_comp_t *ctx) {
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx (TOS) */ spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx (TOS) */
spl_emit(ctx, SPL_LADDR, SPL_PTR, idx_slot); spl_emit(ctx, SPL_LADDR, SPL_PTR, idx_slot);
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_STORE, SPL_I32, 0); spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
} }
/* Load slice[idx] and store to val */ /* Load slice[idx] and store to val */
@@ -459,8 +461,8 @@ static void parse_for_stmt(spl_comp_t *ctx) {
/* Increment idx */ /* Increment idx */
spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx */ spl_emit(ctx, SPL_PICK, SPL_VOID, 0); /* copy idx */
spl_emit(ctx, SPL_PUSH, SPL_I32, 1); spl_emit(ctx, SPL_PUSH, SPL_USIZE, 1);
spl_emit(ctx, SPL_ADD, SPL_I32, 0); spl_emit(ctx, SPL_ADD, SPL_USIZE, 0);
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0); spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* replace old idx with new */ spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* replace old idx with new */
@@ -629,14 +631,23 @@ static void parse_expr_stmt(spl_comp_t *ctx) {
int prev = ctx->tok_idx; int prev = ctx->tok_idx;
/* Look ahead past newlines for assignment operator */ /* Look ahead for assignment operator (scan past expression tokens) */
int is_assign = 0; int is_assign = 0;
if (peek(ctx)->type == TOK_IDENT) { {
usize look = ctx->tok_idx + 1; usize look = ctx->tok_idx;
while (look < vec_size(ctx->toks) && vec_at(ctx->toks, look).type == TOK_ENDLINE) while (look < vec_size(ctx->toks)) {
spl_tok_type_t t = vec_at(ctx->toks, look).type;
if (t == TOK_SEMICOLON || t == TOK_ENDLINE || t == TOK_L_BRACE || t == TOK_R_BRACE ||
t == TOK_EOF)
break;
if (t == TOK_L_PAREN)
break; /* function call, not assignment */
if (is_assign_op(t)) {
is_assign = 1;
break;
}
look++; look++;
if (look < vec_size(ctx->toks)) }
is_assign = is_assign_op(vec_at(ctx->toks, look).type);
} }
if (is_assign) if (is_assign)