stage1 修改部分测试 完成17-19测试
This commit is contained in:
@@ -207,7 +207,7 @@ int spl_prog_load_from_file(const char *fname, spl_prog_t *prog) {
|
|||||||
|
|
||||||
int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
|
int spl_prog_store_to_file(const char *fname, spl_prog_t *prog) {
|
||||||
unsigned char *buf, *p;
|
unsigned char *buf, *p;
|
||||||
int i;
|
spl_val_t i;
|
||||||
size_t total;
|
size_t total;
|
||||||
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
spl_val_t nfuncs, ninsns, nnatives, nstrs, ndata;
|
||||||
usize nlen, pad;
|
usize nlen, pad;
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) {
|
|||||||
int arg_idx = 0;
|
int arg_idx = 0;
|
||||||
char tmp_buf[32];
|
char tmp_buf[32];
|
||||||
memset(tmp_buf, 0, sizeof(tmp_buf));
|
memset(tmp_buf, 0, sizeof(tmp_buf));
|
||||||
for (int i = 0; i < fmt_len; ++i) {
|
for (usize i = 0; i < fmt_len; ++i) {
|
||||||
if (fmt[i] != '%') {
|
if (fmt[i] != '%') {
|
||||||
vec_push(buffer, fmt[i]);
|
vec_push(buffer, fmt[i]);
|
||||||
continue;
|
continue;
|
||||||
@@ -192,7 +192,7 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) {
|
|||||||
switch (fmt[i]) {
|
switch (fmt[i]) {
|
||||||
case 'd':
|
case 'd':
|
||||||
snprintf(tmp_buf, sizeof(tmp_buf), "%zd", args[arg_idx]);
|
snprintf(tmp_buf, sizeof(tmp_buf), "%zd", args[arg_idx]);
|
||||||
for (int j = 0; j < strlen(tmp_buf); ++j) {
|
for (usize j = 0; j < strlen(tmp_buf); ++j) {
|
||||||
vec_push(buffer, tmp_buf[j]);
|
vec_push(buffer, tmp_buf[j]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -200,7 +200,7 @@ static spl_val_t vm_printf(int nargs, spl_val_t *args) {
|
|||||||
vec_push(buffer, (char)args[arg_idx]);
|
vec_push(buffer, (char)args[arg_idx]);
|
||||||
break;
|
break;
|
||||||
case 's':
|
case 's':
|
||||||
for (int j = 0; j < strlen((const char *)args[arg_idx]); ++j) {
|
for (usize j = 0; j < strlen((const char *)args[arg_idx]); ++j) {
|
||||||
vec_push(buffer, ((const char *)args[arg_idx])[j]);
|
vec_push(buffer, ((const char *)args[arg_idx])[j]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -76,10 +76,10 @@ static int spl_type_size(spl_type_t t) {
|
|||||||
do { \
|
do { \
|
||||||
if (vm->sp >= vm->config.max_stack_depth) \
|
if (vm->sp >= vm->config.max_stack_depth) \
|
||||||
VM_ERROR("stack overflow"); \
|
VM_ERROR("stack overflow"); \
|
||||||
vm->stacks.data[vm->sp++] = (spl_val_t)(v); \
|
vm->stacks.data[(vm->sp)++] = (spl_val_t)(v); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define POP() vm->stacks.data[--vm->sp]
|
#define POP() vm->stacks.data[--(vm->sp)]
|
||||||
|
|
||||||
/* ================================================================
|
/* ================================================================
|
||||||
* Type-dispatch macros for arithmetic / comparison
|
* Type-dispatch macros for arithmetic / comparison
|
||||||
@@ -641,7 +641,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
|||||||
return -1;
|
return -1;
|
||||||
prog = vm->prog;
|
prog = vm->prog;
|
||||||
|
|
||||||
if (vm->ip < 0 || vm->ip >= vec_size(prog->insns)) {
|
if (vm->ip >= vec_size(prog->insns)) {
|
||||||
fprintf(stderr, "vm: ip=%zd out of bounds\n", vm->ip);
|
fprintf(stderr, "vm: ip=%zd out of bounds\n", vm->ip);
|
||||||
vm->exit_code = 1;
|
vm->exit_code = 1;
|
||||||
return -1;
|
return -1;
|
||||||
@@ -687,7 +687,7 @@ int spl_vm_run_once(spl_vm_t *vm) {
|
|||||||
|
|
||||||
case SPL_PICK: {
|
case SPL_PICK: {
|
||||||
isize _idx = ins->imm;
|
isize _idx = ins->imm;
|
||||||
if (_idx >= vm->sp)
|
if ((usize)_idx >= vm->sp)
|
||||||
VM_ERROR("PICK: index out of range");
|
VM_ERROR("PICK: index out of range");
|
||||||
PUSH(vm->stacks.data[vm->sp - 1 - _idx]);
|
PUSH(vm->stacks.data[vm->sp - 1 - _idx]);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -6,16 +6,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
/* ============================================================
|
|
||||||
* Token helpers
|
|
||||||
* ============================================================ */
|
|
||||||
|
|
||||||
/* Check if current token starts a statement */
|
|
||||||
static int is_stmt_start(spl_comp_t *ctx) {
|
|
||||||
spl_tok_type_t t = peek(ctx)->type;
|
|
||||||
return t == TOK_EOF || t == TOK_R_BRACE ? 0 : 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* Precedence table
|
* Precedence table
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
@@ -71,7 +61,6 @@ static int tok_prec(spl_tok_type_t t) {
|
|||||||
* Forward declarations
|
* Forward declarations
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
|
|
||||||
static spl_expr_result_t parse_prefix(spl_comp_t *ctx);
|
|
||||||
static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, spl_tok_type_t op);
|
static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, spl_tok_type_t op);
|
||||||
|
|
||||||
/* Slice creation from array/slice range expression.
|
/* Slice creation from array/slice range expression.
|
||||||
@@ -544,29 +533,6 @@ static spl_expr_result_t parse_struct_literal(spl_comp_t *ctx, spl_type_info_t *
|
|||||||
return (spl_expr_result_t){type, 1}; /* address on stack */
|
return (spl_expr_result_t){type, 1}; /* address on stack */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
static spl_type_info_t *parse_qualified_type(spl_comp_t *ctx, const char *name) {
|
|
||||||
/* Check if it's a known type */
|
|
||||||
spl_type_info_t *t = spl_resolve_type(ctx, name);
|
|
||||||
if (t && peek(ctx)->type == TOK_DOT) {
|
|
||||||
/* Enum type with variant: Type.variant */
|
|
||||||
advance(ctx); /* skip . */
|
|
||||||
spl_tok_t *vtok = advance(ctx);
|
|
||||||
char vname[256];
|
|
||||||
usize vn = vtok->len < 255 ? vtok->len : 255;
|
|
||||||
memcpy(vname, vtok->lexeme, vn);
|
|
||||||
vname[vn] = '\0';
|
|
||||||
/* For enum values, just emit the tag as integer */
|
|
||||||
if (t->kind == TYPE_ENUM) {
|
|
||||||
vec_for(t->variants, vi) {
|
|
||||||
if (strcmp(vec_at(t->variants, vi).name, vname) == 0) {
|
|
||||||
spl_emit(ctx, SPL_PUSH, SPL_I32, vec_at(t->variants, vi).value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}
|
|
||||||
|
|
||||||
static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
|
static spl_expr_result_t parse_ident(spl_comp_t *ctx) {
|
||||||
spl_tok_t *t = advance(ctx);
|
spl_tok_t *t = advance(ctx);
|
||||||
@@ -1045,16 +1011,14 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
|||||||
} else if (strcmp(fname, "ptr") == 0) {
|
} else if (strcmp(fname, "ptr") == 0) {
|
||||||
if (ctx->addr_of_mode) {
|
if (ctx->addr_of_mode) {
|
||||||
/* lvalue: ptr is at offset 0, address already on stack */
|
/* lvalue: ptr is at offset 0, address already on stack */
|
||||||
left = (spl_expr_result_t){
|
left = (spl_expr_result_t){left.type->elem ? spl_type_ptr(left.type->elem)
|
||||||
left.type->elem ? spl_type_ptr(left.type->elem)
|
: spl_type_basic(SPL_PTR),
|
||||||
: spl_type_basic(SPL_PTR),
|
1};
|
||||||
1};
|
|
||||||
} else {
|
} else {
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
||||||
left = (spl_expr_result_t){
|
left = (spl_expr_result_t){left.type->elem ? spl_type_ptr(left.type->elem)
|
||||||
left.type->elem ? spl_type_ptr(left.type->elem)
|
: spl_type_basic(SPL_PTR),
|
||||||
: spl_type_basic(SPL_PTR),
|
0};
|
||||||
0};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
@@ -1094,11 +1058,8 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for slice: expr[begin..end] or expr[begin..] */
|
/* Check for slice: expr[begin..end] or expr[begin..] */
|
||||||
int is_slice = 0;
|
|
||||||
usize slice_start = ctx->tok_idx;
|
|
||||||
spl_expr_result_t index = spl_parse_expr(ctx, PREC_MIN);
|
spl_expr_result_t index = spl_parse_expr(ctx, PREC_MIN);
|
||||||
if (peek(ctx)->type == TOK_RANGE) {
|
if (peek(ctx)->type == TOK_RANGE) {
|
||||||
is_slice = 1;
|
|
||||||
advance(ctx); /* skip .. */
|
advance(ctx); /* skip .. */
|
||||||
spl_expr_result_t end_expr = {0};
|
spl_expr_result_t end_expr = {0};
|
||||||
int has_explicit_end = (peek(ctx)->type != TOK_R_BRACKET);
|
int has_explicit_end = (peek(ctx)->type != TOK_R_BRACKET);
|
||||||
@@ -1125,16 +1086,28 @@ spl_expr_result_t spl_parse_expr(spl_comp_t *ctx, int min_prec) {
|
|||||||
if (left.type && (left.type->kind == TYPE_ARRAY || left.type->kind == TYPE_SLICE)) {
|
if (left.type && (left.type->kind == TYPE_ARRAY || left.type->kind == TYPE_SLICE)) {
|
||||||
usize stride = spl_type_elem_stride(left.type->elem);
|
usize stride = spl_type_elem_stride(left.type->elem);
|
||||||
|
|
||||||
/* For TYPE_SLICE: convert [struct_addr, begin, end] → [data_ptr, begin, end] */
|
|
||||||
if (left.type->kind == TYPE_SLICE) {
|
if (left.type->kind == TYPE_SLICE) {
|
||||||
|
/* Stack: [struct_addr, begin, end].
|
||||||
|
* Inline ptr/len: ptr = data_ptr + begin*stride, len = end - begin. */
|
||||||
spl_emit(ctx, SPL_PICK, SPL_VOID, 2);
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 2);
|
||||||
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0);
|
spl_emit(ctx, SPL_LOAD, SPL_PTR, 0); /* [s,b,e,data_ptr] */
|
||||||
spl_emit(ctx, SPL_ROT, SPL_VOID, 0);
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 2); /* [s,b,e,d,begin] */
|
||||||
spl_emit(ctx, SPL_ROT, SPL_VOID, 0);
|
spl_emit(ctx, SPL_PUSH, SPL_U64, stride);
|
||||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_MUL, SPL_U64, 0);
|
||||||
|
spl_emit(ctx, SPL_ADD, SPL_U64, 0); /* [s,b,e,ptr] */
|
||||||
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 1); /* [s,b,e,ptr,end] */
|
||||||
|
spl_emit(ctx, SPL_PICK, SPL_VOID, 3); /* [s,b,e,ptr,end,begin] */
|
||||||
|
spl_emit(ctx, SPL_SUB, SPL_USIZE, 0); /* [s,b,e,ptr,len] */
|
||||||
|
/* cleanup: drop [s,b,e] */
|
||||||
|
spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [s,b,ptr,len,e] */
|
||||||
|
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* [s,b,ptr,len] */
|
||||||
|
spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [s,ptr,len,b] */
|
||||||
|
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* [s,ptr,len] */
|
||||||
|
spl_emit(ctx, SPL_ROT, SPL_VOID, 0); /* [ptr,len,s] */
|
||||||
|
spl_emit(ctx, SPL_DROP, SPL_VOID, 0); /* [ptr,len] */
|
||||||
|
} else {
|
||||||
|
emit_slice_create(ctx, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_slice_create(ctx, stride);
|
|
||||||
}
|
}
|
||||||
left = (spl_expr_result_t){left.type ? spl_type_slice(left.type->elem) : NULL, 0};
|
left = (spl_expr_result_t){left.type ? spl_type_slice(left.type->elem) : NULL, 0};
|
||||||
continue;
|
continue;
|
||||||
@@ -1196,14 +1169,14 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
|
|||||||
if (op == TOK_AND_AND) {
|
if (op == TOK_AND_AND) {
|
||||||
/* left is already evaluated and on stack. If it's false (0), skip right. */
|
/* left is already evaluated and on stack. If it's false (0), skip right. */
|
||||||
spl_val_t bz_addr = spl_emit_bz(ctx);
|
spl_val_t bz_addr = spl_emit_bz(ctx);
|
||||||
spl_expr_result_t right = spl_parse_expr(ctx, next_prec);
|
spl_parse_expr(ctx, next_prec);
|
||||||
spl_patch_to_here(ctx, bz_addr);
|
spl_patch_to_here(ctx, bz_addr);
|
||||||
return (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
|
return (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
|
||||||
}
|
}
|
||||||
if (op == TOK_OR_OR) {
|
if (op == TOK_OR_OR) {
|
||||||
/* If left is true (non-zero), skip right. */
|
/* If left is true (non-zero), skip right. */
|
||||||
spl_val_t bnz_addr = spl_emit_bnz(ctx);
|
spl_val_t bnz_addr = spl_emit_bnz(ctx);
|
||||||
spl_expr_result_t right = spl_parse_expr(ctx, next_prec);
|
spl_parse_expr(ctx, next_prec);
|
||||||
spl_patch_to_here(ctx, bnz_addr);
|
spl_patch_to_here(ctx, bnz_addr);
|
||||||
return (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
|
return (spl_expr_result_t){spl_type_basic(SPL_I32), 0};
|
||||||
}
|
}
|
||||||
@@ -1244,7 +1217,7 @@ static spl_expr_result_t parse_infix(spl_comp_t *ctx, spl_expr_result_t left, sp
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Regular binary op */
|
/* Regular binary op */
|
||||||
spl_expr_result_t right = spl_parse_expr(ctx, next_prec);
|
spl_parse_expr(ctx, next_prec);
|
||||||
int sop = binop_to_sir(op, left.type ? left.type->basic_type : SPL_I32);
|
int sop = binop_to_sir(op, left.type ? left.type->basic_type : SPL_I32);
|
||||||
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 : SPL_I32;
|
||||||
if (sop >= 0) {
|
if (sop >= 0) {
|
||||||
|
|||||||
@@ -96,7 +96,44 @@ static void parse_var_decl(spl_comp_t *ctx, int is_const) {
|
|||||||
|
|
||||||
/* Store init value */
|
/* Store init value */
|
||||||
if (has_init) {
|
if (has_init) {
|
||||||
if (var_type && (var_type->kind == TYPE_STRUCT || var_type->kind == TYPE_ENUM)) {
|
/* Handle slice struct literal: { .ptr = ..., .len = ... } */
|
||||||
|
if (var_type && var_type->kind == TYPE_SLICE && peek(ctx)->type == TOK_L_BRACE && !init.type) {
|
||||||
|
advance(ctx); /* { */
|
||||||
|
skip_nl(ctx);
|
||||||
|
while (peek(ctx)->type != TOK_R_BRACE && peek(ctx)->type != TOK_EOF) {
|
||||||
|
if (peek(ctx)->type == TOK_COMMA) {
|
||||||
|
advance(ctx);
|
||||||
|
skip_nl(ctx);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (peek(ctx)->type == TOK_DOT)
|
||||||
|
advance(ctx);
|
||||||
|
spl_tok_t *ftok = advance(ctx);
|
||||||
|
char fname[256];
|
||||||
|
usize fnl = ftok->len < 255 ? ftok->len : 255;
|
||||||
|
memcpy(fname, ftok->lexeme, fnl);
|
||||||
|
fname[fnl] = '\0';
|
||||||
|
skip_nl(ctx);
|
||||||
|
if (peek(ctx)->type == TOK_ASSIGN)
|
||||||
|
advance(ctx);
|
||||||
|
skip_nl(ctx);
|
||||||
|
|
||||||
|
spl_expr_result_t fv = spl_parse_expr(ctx, PREC_MIN);
|
||||||
|
(void)fv;
|
||||||
|
|
||||||
|
if (strcmp(fname, "ptr") == 0) {
|
||||||
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset);
|
||||||
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
|
spl_emit(ctx, SPL_STORE, SPL_PTR, 0);
|
||||||
|
} else if (strcmp(fname, "len") == 0) {
|
||||||
|
spl_emit(ctx, SPL_LADDR, SPL_PTR, offset + (int)sizeof(spl_val_t));
|
||||||
|
spl_emit(ctx, SPL_SWAP, SPL_VOID, 0);
|
||||||
|
spl_emit(ctx, SPL_STORE, SPL_USIZE, 0);
|
||||||
|
}
|
||||||
|
skip_nl(ctx);
|
||||||
|
}
|
||||||
|
expect(ctx, TOK_R_BRACE);
|
||||||
|
} else if (var_type && (var_type->kind == TYPE_STRUCT || var_type->kind == TYPE_ENUM)) {
|
||||||
/* Struct/enum initialization */
|
/* Struct/enum initialization */
|
||||||
usize sz = spl_type_size(var_type);
|
usize sz = spl_type_size(var_type);
|
||||||
if (sz <= sizeof(spl_val_t)) {
|
if (sz <= sizeof(spl_val_t)) {
|
||||||
@@ -364,7 +401,6 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ===== Slice iteration: for slice [as val |, range as val, idx] ===== */
|
/* ===== Slice iteration: for slice [as val |, range as val, idx] ===== */
|
||||||
int has_idx = 0;
|
|
||||||
if (peek(ctx)->type == TOK_COMMA) {
|
if (peek(ctx)->type == TOK_COMMA) {
|
||||||
advance(ctx); /* , */
|
advance(ctx); /* , */
|
||||||
spl_parse_expr(ctx, PREC_MIN); /* parse start of range (e.g. 0) */
|
spl_parse_expr(ctx, PREC_MIN); /* parse start of range (e.g. 0) */
|
||||||
@@ -376,7 +412,6 @@ static void parse_for_stmt(spl_comp_t *ctx) {
|
|||||||
peek(ctx)->type != TOK_EOF)
|
peek(ctx)->type != TOK_EOF)
|
||||||
spl_parse_expr(ctx, PREC_MIN);
|
spl_parse_expr(ctx, PREC_MIN);
|
||||||
}
|
}
|
||||||
has_idx = 1;
|
|
||||||
/* Range pushed a value; we manage our own idx, drop it */
|
/* Range pushed a value; we manage our own idx, drop it */
|
||||||
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
spl_emit(ctx, SPL_DROP, SPL_VOID, 0);
|
||||||
}
|
}
|
||||||
@@ -614,7 +649,6 @@ static void parse_match_stmt(spl_comp_t *ctx) {
|
|||||||
|
|
||||||
/* Find the variant in the enum type */
|
/* Find the variant in the enum type */
|
||||||
spl_enum_variant_t *variant = NULL;
|
spl_enum_variant_t *variant = NULL;
|
||||||
int vi;
|
|
||||||
vec_for(enum_type->variants, vi) {
|
vec_for(enum_type->variants, vi) {
|
||||||
if (strcmp(vec_at(enum_type->variants, vi).name, vname) == 0) {
|
if (strcmp(vec_at(enum_type->variants, vi).name, vname) == 0) {
|
||||||
variant = &vec_at(enum_type->variants, vi);
|
variant = &vec_at(enum_type->variants, vi);
|
||||||
@@ -853,7 +887,7 @@ static void parse_expr_stmt(spl_comp_t *ctx) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int prev = ctx->tok_idx;
|
usize prev = ctx->tok_idx;
|
||||||
|
|
||||||
/* Look ahead for assignment operator (scan past expression tokens) */
|
/* Look ahead for assignment operator (scan past expression tokens) */
|
||||||
int is_assign = 0;
|
int is_assign = 0;
|
||||||
|
|||||||
@@ -46,12 +46,12 @@ fn main() i32 {
|
|||||||
if r != 25 { ret 6; }
|
if r != 25 { ret 6; }
|
||||||
|
|
||||||
/* 结构体嵌套 */
|
/* 结构体嵌套 */
|
||||||
type Inner = struct {
|
|
||||||
val: i32,
|
|
||||||
}
|
|
||||||
type Outer = struct {
|
type Outer = struct {
|
||||||
inner: Inner,
|
inner: Inner,
|
||||||
extra: i32,
|
extra: i32,
|
||||||
|
type Inner = struct {
|
||||||
|
val: i32,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var o: Outer;
|
var o: Outer;
|
||||||
|
|||||||
184
stage1/test19_hardarray.spl
Normal file
184
stage1/test19_hardarray.spl
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/* ===== 进阶数组与切片 =====
|
||||||
|
* test19_hardarray — 多维数组、多维切片、切片构造、字符串测试
|
||||||
|
* 难度:4/5
|
||||||
|
* 验证点:多维数组索引与修改、多维切片、切片字段读写、扁平指针访问、字符串切片
|
||||||
|
*/
|
||||||
|
fn test_string() i32 {
|
||||||
|
/* ============================
|
||||||
|
* String test: str is []u8
|
||||||
|
* ============================ */
|
||||||
|
var data: *u8 = "hello";
|
||||||
|
var s: []u8 = { .ptr = data, .len = 5 };
|
||||||
|
|
||||||
|
if s.len != 5 { ret 100; }
|
||||||
|
if s[0] != 104 { ret 101; } /* 'h' */
|
||||||
|
if s[1] != 101 { ret 102; } /* 'e' */
|
||||||
|
if s[4] != 111 { ret 103; } /* 'o' */
|
||||||
|
|
||||||
|
/* Slice the string slice */
|
||||||
|
var sub: []u8 = s[1..4];
|
||||||
|
if sub.len != 3 { ret 104; }
|
||||||
|
if sub[0] != 101 { ret 105; } /* 'e' */
|
||||||
|
if sub[2] != 108 { ret 106; } /* 'l' */
|
||||||
|
|
||||||
|
/* Modify through slice → original changes */
|
||||||
|
s[0] = 72; /* 'H' */
|
||||||
|
if data[0] != 72 { ret 107; }
|
||||||
|
|
||||||
|
/* Full slice */
|
||||||
|
var full: []u8 = s[0..];
|
||||||
|
if full.len != 5 { ret 108; }
|
||||||
|
if full[0] != 72 { ret 109; }
|
||||||
|
|
||||||
|
/* Construct slice from pointer via field assignment */
|
||||||
|
var s2: []u8;
|
||||||
|
s2.ptr = data;
|
||||||
|
s2.len = 3;
|
||||||
|
if s2.len != 3 { ret 110; }
|
||||||
|
if s2[0] != 72 { ret 111; }
|
||||||
|
|
||||||
|
ret 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() i32 {
|
||||||
|
/* ============================
|
||||||
|
* Part 1: 多维数组(逐元素初始化)
|
||||||
|
* ============================ */
|
||||||
|
var matrix: [2][3]i32;
|
||||||
|
matrix[0][0] = 1; matrix[0][1] = 2; matrix[0][2] = 3;
|
||||||
|
matrix[1][0] = 4; matrix[1][1] = 5; matrix[1][2] = 6;
|
||||||
|
|
||||||
|
if matrix[0][0] != 1 { ret 1; }
|
||||||
|
if matrix[0][1] != 2 { ret 2; }
|
||||||
|
if matrix[0][2] != 3 { ret 3; }
|
||||||
|
if matrix[1][0] != 4 { ret 4; }
|
||||||
|
if matrix[1][1] != 5 { ret 5; }
|
||||||
|
if matrix[1][2] != 6 { ret 6; }
|
||||||
|
|
||||||
|
/* 元素修改 */
|
||||||
|
matrix[0][0] = 10;
|
||||||
|
matrix[1][2] = 60;
|
||||||
|
if matrix[0][0] != 10 { ret 7; }
|
||||||
|
if matrix[1][2] != 60 { ret 8; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 2: 嵌套循环遍历多维数组
|
||||||
|
* ============================ */
|
||||||
|
var big: [3][4]i32;
|
||||||
|
big[0][0] = 1; big[0][1] = 2; big[0][2] = 3; big[0][3] = 4;
|
||||||
|
big[1][0] = 5; big[1][1] = 6; big[1][2] = 7; big[1][3] = 8;
|
||||||
|
big[2][0] = 9; big[2][1] = 10; big[2][2] = 11; big[2][3] = 12;
|
||||||
|
|
||||||
|
var total: i32 = 0;
|
||||||
|
var i: i32 = 0;
|
||||||
|
while i < 3 {
|
||||||
|
var j: i32 = 0;
|
||||||
|
while j < 4 {
|
||||||
|
total = total + big[i][j];
|
||||||
|
j = j + 1;
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
if total != 78 { ret 9; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 3: &取地址 + 扁平指针访问
|
||||||
|
* ============================ */
|
||||||
|
var flat: *i32 = &matrix[0][0];
|
||||||
|
if flat[0] != 10 { ret 10; }
|
||||||
|
if flat[1] != 2 { ret 11; }
|
||||||
|
if flat[2] != 3 { ret 12; }
|
||||||
|
if flat[3] != 4 { ret 13; }
|
||||||
|
if flat[4] != 5 { ret 14; }
|
||||||
|
if flat[5] != 60 { ret 15; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 4: 多维数组切片
|
||||||
|
* ============================ */
|
||||||
|
var row: []i32 = matrix[0][0..3];
|
||||||
|
if row.len != 3 { ret 16; }
|
||||||
|
if row[0] != 10 { ret 17; }
|
||||||
|
if row[1] != 2 { ret 18; }
|
||||||
|
if row[2] != 3 { ret 19; }
|
||||||
|
|
||||||
|
/* 切取第二行 */
|
||||||
|
var row2: []i32 = matrix[1][0..];
|
||||||
|
if row2.len != 3 { ret 20; }
|
||||||
|
if row2[0] != 4 { ret 21; }
|
||||||
|
if row2[2] != 60 { ret 22; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 5: 切片的切片
|
||||||
|
* ============================ */
|
||||||
|
var sub: []i32 = row[1..3];
|
||||||
|
if sub.len != 2 { ret 23; }
|
||||||
|
if sub[0] != 2 { ret 24; }
|
||||||
|
if sub[1] != 3 { ret 25; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 6: 切片字段读写
|
||||||
|
* ============================ */
|
||||||
|
var arr: [4]i32;
|
||||||
|
arr[0] = 100; arr[1] = 200; arr[2] = 300; arr[3] = 400;
|
||||||
|
var custom: []i32;
|
||||||
|
custom.ptr = &arr[1];
|
||||||
|
custom.len = 2;
|
||||||
|
|
||||||
|
if custom.len != 2 { ret 26; }
|
||||||
|
if custom[0] != 200 { ret 27; }
|
||||||
|
if custom[1] != 300 { ret 28; }
|
||||||
|
|
||||||
|
/* 修改切片长度 */
|
||||||
|
custom.len = 3;
|
||||||
|
if custom.len != 3 { ret 29; }
|
||||||
|
if custom[2] != 400 { ret 30; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 7: 空范围 / 全切片
|
||||||
|
* ============================ */
|
||||||
|
var full: []i32 = arr[0..];
|
||||||
|
if full.len != 4 { ret 31; }
|
||||||
|
if full[0] != 100 { ret 32; }
|
||||||
|
if full[3] != 400 { ret 33; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 8: 从指针构造切片
|
||||||
|
* ============================ */
|
||||||
|
var data: [5]i32;
|
||||||
|
data[0] = 10; data[1] = 20; data[2] = 30; data[3] = 40; data[4] = 50;
|
||||||
|
var p: *i32 = &data[2];
|
||||||
|
var from_ptr: []i32 = { .ptr = p, .len = 2 };
|
||||||
|
var from_ptr2: []i32;
|
||||||
|
from_ptr2.ptr = p;
|
||||||
|
from_ptr2.len = 2;
|
||||||
|
|
||||||
|
if from_ptr.len != 2 { ret 34; }
|
||||||
|
if from_ptr[0] != 30 { ret 35; }
|
||||||
|
if from_ptr[1] != 40 { ret 36; }
|
||||||
|
|
||||||
|
if from_ptr2.len != 2 { ret 37; }
|
||||||
|
if from_ptr2[0] != 30 { ret 38; }
|
||||||
|
if from_ptr2[1] != 40 { ret 39; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 9: 切片元素修改反映到原始数组
|
||||||
|
* ============================ */
|
||||||
|
row2[0] = 99;
|
||||||
|
if matrix[1][0] != 99 { ret 40; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 10: 1D 数组字面量仍然正常
|
||||||
|
* ============================ */
|
||||||
|
var literal: [3]i32 = [3]i32{10, 20, 30};
|
||||||
|
if literal[0] != 10 { ret 41; }
|
||||||
|
if literal[1] != 20 { ret 42; }
|
||||||
|
if literal[2] != 30 { ret 43; }
|
||||||
|
|
||||||
|
/* ============================
|
||||||
|
* Part 11: 字符串切片测试
|
||||||
|
* ============================ */
|
||||||
|
var r: i32 = test_string();
|
||||||
|
if r != 0 { ret r; }
|
||||||
|
|
||||||
|
ret 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user