diff --git a/stage0/spl_vm.c b/stage0/spl_vm.c index aeb7a07..9bc60a4 100644 --- a/stage0/spl_vm.c +++ b/stage0/spl_vm.c @@ -548,7 +548,7 @@ void spl_vm_init_ex(spl_vm_t *vm, int stack_size, int call_depth) { #endif if (!vm) return; - vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 8; + vm->config.max_stack_depth = stack_size > 0 ? stack_size : 1024 * 1024 * 8; vm->config.max_call_depth = call_depth > 0 ? call_depth : 128; vec_init(vm->stacks); @@ -989,6 +989,8 @@ int spl_vm_run_once(spl_vm_t *vm) { } case SPL_HALT: + if (ins->imm) + vm->exit_code = (int)ins->imm; return 1; /* ========== Stack / Frame Local Memory ========== */ diff --git a/stage1/spl_ast.c b/stage1/spl_ast.c index 454b58c..477b1bc 100644 --- a/stage1/spl_ast.c +++ b/stage1/spl_ast.c @@ -1786,10 +1786,11 @@ static spl_ast_node_ref_t parse_type_atom(parser_t *p) { kind = SPL_AST_TYPE_USIZE; else if (IS_TY("ptr")) kind = SPL_AST_TYPE_PTR; - else if (IS_TY("f32") || IS_TY("f64")) { - parse_error(p, t, "not implemented: f32/f64 type"); - kind = SPL_AST_TYPE_IDENT; - } else { + else if (IS_TY("f32")) + kind = SPL_AST_TYPE__F32; + else if (IS_TY("f64")) + kind = SPL_AST_TYPE__F64; + else { kind = SPL_AST_TYPE_IDENT; } #undef IS_TY diff --git a/stage1/spl_ast2ir.c b/stage1/spl_ast2ir.c index 305182f..98bbd30 100644 --- a/stage1/spl_ast2ir.c +++ b/stage1/spl_ast2ir.c @@ -3,11 +3,12 @@ * 设计要点 * - 名称解析自包含:局部变类型用自身环境栈;顶层类函数sema root scope 与聚合成员表 * - * 变量落在内存槽(@mem.alloca),写走 @mem.load/store;表达式临时值为 SSA * - 控制流用"块表 + * fixup 补丁":分跳转目标在函数末尾回填为块首指令node ref * - - * 聚合字段访问:读@agg.extract,写字节地址直写"(@mem.offset + @mem.store�?* - 枚举= + * 聚合字段访问:读@agg.extract,写字节地址直写"(@mem.offset + @mem.store* - 枚举= * agg.construct(enum)([tag, payload?]);match tag 分发 * - defer 按作用域逆序执行(正常退/ ret / * break / continue 全覆盖) */ #include "spl_ast2ir.h" +#include "spl_builtin.h" #include #include @@ -133,7 +134,7 @@ static spl_def_id_t def_for_type(spl_ast2ir_t *a, spl_type_id_t tid) { return fallback; } -/* 判断 agg_def 条目是否为结构字段(SPL_DEF_MEMBER�?*/ +/* 判断 agg_def 条目是否为结构字段(SPL_DEF_MEMBER*/ static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) { if (!e->def_id) return 0; @@ -141,7 +142,7 @@ static int agg_entry_is_field(spl_ast2ir_t *a, const spl_var_def_t *e) { return ed && ed->kind == SPL_DEF_MEMBER; } -/* 命名空间成员类型(方�?嵌套类型/static var):按名任意 kind */ +/* 命名空间成员类型(方嵌套类型/static var):按名任意 kind */ static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -155,7 +156,7 @@ static spl_type_id_t agg_member_type(spl_ast2ir_t *a, spl_type_id_t agg_tid, con return 0; } -/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(�?type.agg_field_types 按序对齐�?*/ +/* 结构字段序号 = 相对 SPL_DEF_MEMBER 的位置(type.agg_field_types 按序对齐*/ static isize agg_member_index(spl_ast2ir_t *a, spl_type_id_t agg_tid, const char *name) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -188,7 +189,7 @@ static spl_type_id_t agg_field_tid_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, is return 0; } -/* 按字段序号查成员名(agg_def 中第 idx �?SPL_DEF_MEMBER 条目�?*/ +/* 按字段序号查成员名(agg_def 中第 idx SPL_DEF_MEMBER 条目*/ static const char *agg_field_name_at(spl_ast2ir_t *a, spl_type_id_t agg_tid, isize idx) { agg_tid = underlying(a->sema, agg_tid); spl_def_id_t d = def_for_type(a, agg_tid); @@ -289,6 +290,7 @@ typedef struct { VEC(spl_type_id_t) types; /* nodes 平行的结果类型表 */ int terminated; spl_type_id_t hint; + usize cur_src; /* 当前语句AST 节点 ref(调试行号) */ int err; } fnctx_t; @@ -342,6 +344,7 @@ static spl_ir_node_ref_t emit_node(spl_ast2ir_t *a, fnctx_t *fc) { fc->terminated = 0; } spl_ir_node_ref_t r = spl_ir_alloc_node(&a->ir, fc->fn); + spl_ir_node(&a->ir, fc->fn, r)->src_ref = fc->cur_src; /* 调试行号 */ if (fc->cur_block < fc->blocks.size && !fc->blocks.data[fc->cur_block].first) fc->blocks.data[fc->cur_block].first = r; if (fc->types.size == 0) { @@ -533,7 +536,7 @@ static spl_ir_node_ref_t emit_offset(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t return n; } -/* 字段地址:mem.field_ptr(agg_tid, agg, idx) → *field_type。布局偏移由 ir2vm 算,ast2ir 不算。 */ +/* 字段地址:mem.field_ptr(agg_tid, agg, idx) *field_type。布局偏移ir2vm 算,ast2ir 不算*/ static spl_ir_node_ref_t emit_field(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t agg_tid, spl_ir_node_ref_t ptr, isize fidx) { spl_type_id_t fty = agg_field_tid_or_builtin(a, agg_tid, fidx); @@ -548,7 +551,7 @@ static spl_ir_node_ref_t emit_field(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t return n; } -/* 全局静态数据地址:mem.global_alloc(tid, gdata_idx) �?*tid */ +/* 全局静态数据地址:mem.global_alloc(tid, gdata_idx) *tid */ static spl_ir_node_ref_t emit_global_alloc(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t tid, usize gdata_idx) { spl_ir_node_ref_t n = emit_node(a, fc); @@ -665,7 +668,7 @@ static ir_env_t *env_find(fnctx_t *fc, const char *name) { return NULL; } -/* def_id 优先定位(sema 已作用域解析,绕开同名遮蔽歧义);�?def_id 时兜底名�?*/ +/* def_id 优先定位(sema 已作用域解析,绕开同名遮蔽歧义);def_id 时兜底名*/ static ir_env_t *env_find_def(fnctx_t *fc, spl_def_id_t def_id, const char *name) { if (def_id) { for (usize i = fc->env.size; i > 0; i--) { @@ -740,7 +743,7 @@ static spl_ir_node_ref_t enum_tag_of(spl_ast2ir_t *a, fnctx_t *fc, spl_type_id_t return emit_agg_extract(a, fc, enum_tid, enum_tag_tid(a), 0, val); } -/* tid 是否�?enum */ +/* tid 是否enum */ static int is_enum_expand(spl_ast2ir_t *a, spl_type_id_t tid, spl_type_id_t *out_enum) { spl_type_node_t *t = tn(a->sema, underlying(a->sema, tid)); if (t && t->kind == SPL_TYPE_ENUM) { @@ -865,13 +868,13 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod spl_ast_node_t *n = node_at(a->sema, ref); if (!n) return 0; - /* 首�?sema 注解:resolved_def_id �?def �?类型(聚�?别名/命名类型�?*/ + /* 首sema 注解:resolved_def_id def 类型(聚别名/命名类型*/ if (n->resolved_def_id) { spl_def_node_t *d = def_at(a->sema, n->resolved_def_id); if (d && d->type_id) return d->type_id; } - /* 兜底:组�?内置类型(sema 不为其建 def �?*T、[]T、fn(...)、关键字、别名到组合�?*/ + /* 兜底:组内置类型(sema 不为其建 def *T、[]T、fn(...)、关键字、别名到组合*/ spl_type_id_t base = 0; switch (n->type_expr.kind) { case SPL_AST_BASE_TYPE_PATH: @@ -898,7 +901,7 @@ static spl_type_id_t resolve_type_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod case SPL_AST_TYPE_STRUCT: case SPL_AST_TYPE_UNION: case SPL_AST_TYPE_ENUM: - /* 内联聚合不应走到这里(sema 已注解其 def);防御性报�?*/ + /* 内联聚合不应走到这里(sema 已注解其 def);防御性报*/ diag(a, fc, ref, "inline aggregate not annotated by sema"); return 0; default: @@ -1019,7 +1022,7 @@ static spl_ast_node_ref_t field_chain_base(spl_ast2ir_t *a, spl_ast_node_t *pf, return bref; } -/* 字段链的存储地址(root.a.b 地址 + 字段类型�?*/ +/* 字段链的存储地址(root.a.b 地址 + 字段类型*/ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t bref, spl_type_id_t *out_tid) { spl_ast_node_t *n = node_at(a->sema, bref); @@ -1031,7 +1034,7 @@ static spl_ir_node_ref_t lower_field_address(spl_ast2ir_t *a, fnctx_t *fc, spl_a const char *names[MAX_FIELD_CHAIN]; int nf = 0; spl_ast_node_ref_t root_ref = field_chain_base(a, pf, names, &nf); - /* 类型命名空间基址:Foo.counter(全局 var/const �?lvalue = �?gdata 地址�?*/ + /* 类型命名空间基址:Foo.counter(全局 var/const lvalue = gdata 地址*/ spl_type_id_t ns = type_of_type_ref(a, fc, root_ref); if (ns && nf == 1) { spl_def_id_t gdef = def_for_type(a, ns); @@ -1134,10 +1137,13 @@ static spl_ir_node_ref_t index_addr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t base_addr = base_lv ? emit_load(a, fc, base_t, base_lv) : base_addr; elem_t = underlying(a->sema, bt->ptr_pointee); } else if (bt && bt->kind == SPL_TYPE_SLICE) { - spl_ir_node_ref_t slv = base_lv ? emit_load(a, fc, base_t, base_lv) : base_addr; elem_t = bt->slice_element; - spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, elem_t); - base_addr = emit_agg_extract(a, fc, base_t, ep, 0, slv); + if (base_lv) { + spl_ir_node_ref_t slv = emit_load(a, fc, base_t, base_lv); + spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, elem_t); + base_addr = emit_agg_extract(a, fc, base_t, ep, 0, slv); + } + /* base_lv==0 时 base_addr 已是切片表达式中提取出的 ptr 标量,直接复用 */ } else { diag(a, fc, 0, "index requires array/slice/pointer"); return 0; @@ -1442,7 +1448,7 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod } spl_type_id_t ft = agg_field_tid_or_builtin(a, hint_t, fidx); spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr); - /* 字段是指针、值是聚合 lvalue:自动取地址�?left = expr 语义�?*/ + /* 字段是指针、值是聚合 lvalue:自动取地址left = expr 语义*/ spl_type_node_t *fld_t = ft ? tn(a->sema, ft) : NULL; spl_type_node_t *v_t = tn(a->sema, underlying(a->sema, node_type(fc, v))); if (fld_t && fld_t->kind == SPL_TYPE_PTR && v_t && @@ -1525,7 +1531,7 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod fc->hint = tt->agg_field_types.data[i]; spl_ir_node_ref_t v = lower_expr(a, fc, item->aggregate_init_item.expr); fc->hint = 0; - /* 字段是指针、值是聚合 lvalue:自动取地址�?left = expr 语义�?*/ + /* 字段是指针、值是聚合 lvalue:自动取地址left = expr 语义*/ spl_type_node_t *fld_t = tn(a->sema, tt->agg_field_types.data[i]); spl_type_node_t *v_t = tn(a->sema, underlying(a->sema, node_type(fc, v))); if (fld_t && fld_t->kind == SPL_TYPE_PTR && v_t && @@ -1547,22 +1553,80 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod } case SPL_AST_BUILTIN_EXPR: { const char *id = pn->primary_expr.builtin_expr.ident; - if (strcmp(id, "sizeof") == 0 && pn->primary_expr.builtin_expr.expr_list.size) { + const spl_builtin_t *bi = spl_builtin_lookup(id); + if (!bi) { + diag(a, fc, 0, "unsupported builtin call"); + return 0; + } + usize nargs = pn->primary_expr.builtin_expr.expr_list.size; + if (nargs < (usize)bi->min_args || (bi->max_args >= 0 && nargs > (usize)bi->max_args)) { + diag(a, fc, 0, "builtin @arg count mismatch"); + return 0; + } + /* @sizeof / @bitsizeof / @alignof / @field_count: 单类型参数 → 对应 IR 类型查询节点 */ + if (bi->kind == SPL_BUILTIN_SIZE_OF || bi->kind == SPL_BUILTIN_BITSIZE_OF || + bi->kind == SPL_BUILTIN_ALIGN_OF || bi->kind == SPL_BUILTIN_FIELD_COUNT) { spl_type_id_t t = type_from_type_like(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); if (!t) { - diag(a, fc, 0, "sizeof: cannot resolve type"); + diag(a, fc, 0, "builtin @type query: cannot resolve type"); return 0; } spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); - e->kind = SPL_IR_TYPE_SIZEOF; - e->ir_sizeof.tid = t; + switch (bi->kind) { + case SPL_BUILTIN_SIZE_OF: + e->kind = SPL_IR_TYPE_SIZEOF; + e->ir_sizeof.tid = t; + break; + case SPL_BUILTIN_BITSIZE_OF: + e->kind = SPL_IR_TYPE_BITSIZEOF; + e->bitsizeof.tid = t; + break; + case SPL_BUILTIN_ALIGN_OF: + e->kind = SPL_IR_TYPE_ALIGNOF; + e->ir_alignof.tid = t; + break; + default: + e->kind = SPL_IR_TYPE_FIELD_COUNT; + e->field_count.tid = t; + break; + } set_ntype(fc, n, kw_type(a, "usize")); return n; } - if (strcmp(id, "dbg") == 0) { - for (usize i = 0; i < pn->primary_expr.builtin_expr.expr_list.size; i++) + /* @offsetof(T, field): 字段名 → 索引常量节点 */ + if (bi->kind == SPL_BUILTIN_OFFSET_OF) { + spl_type_id_t t = + type_from_type_like(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); + spl_ast_node_t *farg = + node_at(a->sema, pn->primary_expr.builtin_expr.expr_list.data[1]); + if (!t || !farg || farg->kind != SPL_AST_EXPR) { + diag(a, fc, 0, "@offsetof: invalid arguments"); + return 0; + } + spl_ast_node_t *fn_ = farg->expr.op == SPL_AST_PRIMARY_EXPR + ? node_at(a->sema, farg->expr.op_expr.left) + : NULL; + const char *fname = + (fn_ && fn_->primary_expr.kind == SPL_AST_IDENT) ? fn_->primary_expr.ident : NULL; + isize fidx = fname ? agg_index_or_builtin(a, t, fname) : -1; + if (fidx < 0) { + diag(a, fc, 0, "@offsetof: unknown field"); + return 0; + } + spl_ir_node_ref_t idx = const_int(a, fc, kw_type(a, "usize"), (usize)fidx); + spl_ir_node_ref_t n = emit_node(a, fc); + spl_ir_node_t *e = enode(a, fc, n); + e->kind = SPL_IR_TYPE_OFFSETOF; + e->ir_offsetof.tid = t; + e->ir_offsetof.field_idx = idx; + set_ntype(fc, n, kw_type(a, "usize")); + return n; + } + /* @dbg(args...): 逐参数求值(副作用),发射断点 */ + if (bi->kind == SPL_BUILTIN_DBG) { + for (usize i = 0; i < nargs; i++) lower_expr(a, fc, pn->primary_expr.builtin_expr.expr_list.data[i]); spl_ir_node_ref_t n = emit_node(a, fc); spl_ir_node_t *e = enode(a, fc, n); @@ -1570,7 +1634,31 @@ static spl_ir_node_ref_t lower_primary(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod set_ntype(fc, n, kw_type(a, "void")); return n; } - diag(a, fc, 0, "unsupported builtin call"); + /* @assert(cond): 若 cond 为假 → trap(HALT) */ + if (bi->kind == SPL_BUILTIN_ASSERT) { + spl_ir_node_ref_t c = + lower_expr(a, fc, pn->primary_expr.builtin_expr.expr_list.data[0]); + usize trap_b = new_block(fc); + usize exit_b = new_block(fc); + emit_br(a, fc, c, exit_b, trap_b); + begin_block(fc, trap_b); + { + spl_ir_node_ref_t n = emit_node(a, fc); + spl_ir_node_t *e = enode(a, fc, n); + e->kind = SPL_IR_CONTROL_TRAP; + set_ntype(fc, n, kw_type(a, "void")); + fc->terminated = 1; + } + begin_block(fc, exit_b); + spl_ir_node_ref_t r = emit_node(a, fc); + spl_ir_node_t *e = enode(a, fc, r); + e->kind = SPL_IR_TYPE_CONST; + e->type_const.tid = kw_type(a, "void"); + set_ntype(fc, r, kw_type(a, "void")); + return r; + } + /* @import: 预留未实现 */ + diag(a, fc, 0, "builtin @import not implemented"); return 0; } default: @@ -1719,7 +1807,7 @@ static int resolve_callee(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t base, vt = underlying(a->sema, vtt->ptr_pointee); vtt = tn(a->sema, vt); } - /* enum 方法:在原 enum def 上查找 */ + /* enum 方法:在enum def 上查*/ spl_type_id_t lookup = vt; spl_type_id_t e0 = 0; if (vtt && is_enum_expand(a, vt, &e0)) @@ -1759,7 +1847,7 @@ static spl_ir_node_ref_t lower_field(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ if (vidx >= 0) return enum_variant_value(a, fc, ttr, vidx); } - /* 聚合命名空间成员:static var/const �?全局数据 */ + /* 聚合命名空间成员:static var/const 全局数据 */ spl_def_id_t gdef = def_for_type(a, ttr); spl_def_node_t *gd = gdef ? def_at(a->sema, gdef) : NULL; for (usize i = 0; gd && i < gd->agg_def.size; i++) { @@ -1868,6 +1956,12 @@ static spl_ir_node_ref_t lower_postfix(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod case SPL_AST_SLICE_EXPR: { spl_type_id_t bt = 0; spl_ir_node_ref_t base_lv = lower_lvalue(a, fc, pf->postfix_expr.primary_expr, &bt); + spl_ir_node_ref_t base_val = 0; + if (!base_lv) { + /* base 是切片/数组表达式(如 arr[1..4][1..2]):取值后提取字段 */ + base_val = lower_expr(a, fc, pf->postfix_expr.primary_expr); + bt = node_type(fc, base_val); + } spl_type_node_t *tt = tn(a->sema, underlying(a->sema, bt)); if (!tt || (tt->kind != SPL_TYPE_ARRAY && tt->kind != SPL_TYPE_SLICE)) { diag(a, fc, 0, "slice requires array/slice"); @@ -1882,7 +1976,7 @@ static spl_ir_node_ref_t lower_postfix(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_nod base_ptr = base_lv; total_len = const_int(a, fc, kw_type(a, "usize"), tt->array_type.len); } else { - spl_ir_node_ref_t slv = emit_load(a, fc, bt, base_lv); + spl_ir_node_ref_t slv = base_lv ? emit_load(a, fc, bt, base_lv) : base_val; spl_type_id_t ep = spl_type_ptr((spl_type_t *)&a->sema->type, elem); base_ptr = emit_agg_extract(a, fc, bt, ep, 0, slv); total_len = emit_agg_extract(a, fc, bt, kw_type(a, "usize"), 1, slv); @@ -2167,7 +2261,7 @@ static spl_ir_node_ref_t lower_assign(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node lt = it->tid; target = it->slot; } else { - /* 全局 var(顶�?/ 命名空间裸名�?*/ + /* 全局 var(顶/ 命名空间裸名*/ spl_def_id_t def = pn->resolved_def_id; if (!def) def = root_lookup(a, pn->primary_expr.ident); @@ -2276,6 +2370,8 @@ static spl_ir_node_ref_t lower_expr(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_r spl_ast_node_t *n = node_at(a->sema, ref); if (!n || n->kind != SPL_AST_EXPR) return 0; + if (ref) + fc->cur_src = ref; /* 调试行号:当前语*/ switch (n->expr.op) { case SPL_AST_PRIMARY_EXPR: return lower_primary(a, fc, node_at(a->sema, n->expr.op_expr.left)); @@ -2369,6 +2465,9 @@ static void lower_var_decl(spl_ast2ir_t *a, fnctx_t *fc, const char *name, spl_d emit_store(a, fc, tid, slot, v); } env_add(fc, name, def_id, tid, slot, 0, 0, 1); + /* 调试:登记变量名 alloca 节点 */ + spl_ir_dbg_var_t dv = {name, slot, tid, 0, 0}; + vec_push(a->ir.funcs.data[fc->fn].dbg_vars, dv); } static void lower_if(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { @@ -2468,6 +2567,18 @@ static void for_seq_setup(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t eref, spl_ir_node_ref_t v = lower_expr(a, fc, eref); spl_type_id_t vt = underlying(a->sema, node_type(fc, v)); spl_type_node_t *vtt = vt ? tn(a->sema, vt) : NULL; + if (vtt && vtt->kind == SPL_TYPE_RANGE) { + /* Range 值:内部 { begin, end },迭代 begin..end-1 */ + s->kind = FOR_RANGE; + s->elem_tid = vtt->range_element; + s->begin_slot = emit_alloca(a, fc, s->elem_tid); + emit_store(a, fc, s->elem_tid, s->begin_slot, + emit_agg_extract(a, fc, vt, s->elem_tid, 0, v)); + spl_ir_node_ref_t end = emit_agg_extract(a, fc, vt, s->elem_tid, 1, v); + spl_ir_node_ref_t b = emit_load(a, fc, s->elem_tid, s->begin_slot); + s->len = emit_arith(a, fc, SPL_IR_ARITH_SUB, s->elem_tid, end, b); + return; + } if (vtt && vtt->kind == SPL_TYPE_SLICE) { s->kind = FOR_SLICE; s->elem_tid = vtt->slice_element; @@ -2640,13 +2751,26 @@ static void lower_match(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { emit_jmp(a, fc, body_b); } else { spl_ir_node_ref_t cond = 0; - if (is_enum && pk->packed_expr.ident) { - isize vidx = enum_variant_index(a, st, pk->packed_expr.ident); - if (vidx < 0) - vidx = 0; - spl_ir_node_ref_t tv = emit_load(a, fc, tag_t, tag_slot); - spl_ir_node_ref_t idxc = const_int(a, fc, tag_t, (usize)vidx); - cond = emit_cmp(a, fc, SPL_IR_CMP_EQ, tag_t, tv, idxc); + const char *vname = NULL; + if (is_enum) { + /* 变体名:`.Red`(ident)或 `Tag.ident`(expr 字段路径)两种形式 */ + vname = pk->packed_expr.ident; + if (!vname && pk->packed_expr.expr) { + spl_ast_node_t *en = node_at(a->sema, pk->packed_expr.expr); + if (en && en->kind == SPL_AST_EXPR && en->expr.op == SPL_AST_POSTFIX_EXPR) { + spl_ast_node_t *epf = node_at(a->sema, en->expr.op_expr.left); + if (epf && epf->postfix_expr.kind == SPL_AST_FIELD_EXPR) + vname = epf->postfix_expr.field_expr; + } + } + if (vname) { + isize vidx = enum_variant_index(a, st, vname); + if (vidx < 0) + vidx = 0; + spl_ir_node_ref_t tv = emit_load(a, fc, tag_t, tag_slot); + spl_ir_node_ref_t idxc = const_int(a, fc, tag_t, (usize)vidx); + cond = emit_cmp(a, fc, SPL_IR_CMP_EQ, tag_t, tv, idxc); + } } else if (is_int && pk->packed_expr.expr) { spl_ir_node_ref_t sv = emit_load(a, fc, st, subj_slot); spl_ir_node_ref_t pv = lower_expr(a, fc, pk->packed_expr.expr); @@ -2665,7 +2789,7 @@ static void lower_match(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_t *b) { spl_type_id_t pt = enum_payload_tid(a, st, vidx); if (pt) { spl_ir_node_ref_t sv = emit_load(a, fc, st, subj_slot); - /* enum 布局 = tag(0) + payload(8):直接提�?payload,field_tid = 变体具体类型 */ + /* enum 布局 = tag(0) + payload(8):直接提payload,field_tid = 变体具体类型 */ spl_ir_node_ref_t pv = emit_agg_extract(a, fc, st, pt, 1, sv); spl_ir_node_ref_t bslot = emit_alloca(a, fc, pt); emit_store(a, fc, pt, bslot, pv); @@ -2729,9 +2853,23 @@ static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { case SPL_AST_IF_STATEMENT: lower_if(a, fc, b); break; - case SPL_AST_IFVAR_STATEMENT: - diag(a, fc, ref, "if-var not supported"); + case SPL_AST_IFVAR_STATEMENT: { + /* if var .x[y] = e { }:绑定新变量 y = e,进入 if 块(sema 语义) + * 若 bind_ident 为空(if var .x = e),则不绑定,仅进入 if 块 */ + spl_ast_node_t *pk = node_at(a->sema, b->block_item.ifvar_statement.packed_expr); + if (pk && pk->packed_expr.bind_ident && pk->packed_expr.expr) { + spl_ir_node_ref_t ev = lower_expr(a, fc, pk->packed_expr.expr); + spl_type_id_t vt = underlying(a->sema, node_type(fc, ev)); + spl_ir_node_ref_t bslot = emit_alloca(a, fc, vt); + emit_store(a, fc, vt, bslot, ev); + env_add(fc, pk->packed_expr.bind_ident, 0, vt, bslot, 0, 0, 0); + } + env_push(fc); + lower_block(a, fc, &b->block_item.ifvar_statement.if_block); + env_pop(fc); + /* else 分支:无失败语义,不发射 */ break; + } case SPL_AST_WHILE_STATEMENT: lower_while(a, fc, b); break; @@ -2784,7 +2922,7 @@ static void lower_stmt(spl_ast2ir_t *a, fnctx_t *fc, spl_ast_node_ref_t ref) { * ================================================================ */ static spl_ir_func_ref_t a2ir_fn_of(spl_ast2ir_t *a, spl_type_id_t fn_tid) { - /* 懒扫描:IR func 已记�?fn_tid(spl_type_fn 不去重,fn_tid 唯一�?*/ + /* 懒扫描:IR func 已记fn_tid(spl_type_fn 不去重,fn_tid 唯一*/ for (usize i = 1; i < a->ir.funcs.size; i++) { if (a->ir.funcs.data[i].fn_tid == fn_tid) return i; @@ -2818,6 +2956,9 @@ static void lower_func_body(spl_ast2ir_t *a, spl_ir_func_ref_t fid, spl_type_id_ spl_ir_node_ref_t slot = emit_alloca(a, &fc, pt); emit_store(a, &fc, pt, slot, pr); env_add(&fc, pd->param_decl.name, pd->resolved_def_id, pt, slot, 0, 0, 0); + /* 调试:参数登记(值在参数区,fp 偏移ir2vm param_off 填) */ + spl_ir_dbg_var_t dv = {pd->param_decl.name, slot, pt, 1, (usize)i}; + vec_push(a->ir.funcs.data[fid].dbg_vars, dv); } begin_block(&fc, new_block(&fc)); lower_block(a, &fc, &fn->fn_decl.block); @@ -2870,10 +3011,10 @@ void spl_ast2ir_drop(spl_ast2ir_t *ast2ir) { } /* ================================================================ - * 全局数据(聚合类型下 / 顶层�?var、const�? + * 全局数据(聚合类型下 / 顶层var、const * ================================================================ */ -/* 常量折叠:仅支持字面量(int/char/float/string/null)与一元负�?*/ +/* 常量折叠:仅支持字面量(int/char/float/string/null)与一元负*/ typedef struct { int const_init; isize int_v; @@ -2937,6 +3078,13 @@ static void collect_gdata_list(spl_ast2ir_t *a, spl_ast_node_ref_vec_t *members) } else if (m->kind == SPL_AST_CONST_DECL) { mname = m->const_decl.name; iexpr = m->const_decl.expr; + } else if (m->kind == SPL_AST_MEMBER_DECL) { + /* 顶层裸成员(文件级 IDENT: T)视为全局 var;聚合体内 MEMBER_DECL 是字段不收集 */ + spl_def_node_t *md = m->resolved_def_id ? def_at(a->sema, m->resolved_def_id) : NULL; + if (!md || md->kind != SPL_DEF_VAR) + continue; + mname = m->member_decl.name; + iexpr = 0; } else { continue; } @@ -2950,7 +3098,7 @@ static void collect_gdata_list(spl_ast2ir_t *a, spl_ast_node_ref_vec_t *members) spl_type_id_t g_tid = d->type_id; if (iexpr) fold_const_init(a, iexpr, &g); - /* 全局 value = type.const 节点(标量折叠值;聚合/无 init 零) */ + /* 全局 value = type.const 节点(标量折叠值;聚合/init 零) */ spl_ir_node_t v; memset(&v, 0, sizeof v); v.kind = SPL_IR_TYPE_CONST; @@ -2987,7 +3135,7 @@ static void collect_gdata(spl_ast2ir_t *a) { } } -/* def_id �?gdata value 节点索引;未命中返回 -1 */ +/* def_id gdata value 节点索引;未命中返回 -1 */ static isize gdata_index_by_def(spl_ast2ir_t *a, spl_def_id_t def_id) { for (usize i = 0; i < a->gdata_ref.size; i++) if (a->gdata_ref.data[i].def_id == def_id) diff --git a/stage1/spl_builtin.c b/stage1/spl_builtin.c new file mode 100644 index 0000000..373cb6d --- /dev/null +++ b/stage1/spl_builtin.c @@ -0,0 +1,28 @@ +/* spl_builtin.c — 内置函数集中注册表实现 */ + +#include "spl_builtin.h" +#include "../stage0/include/utils.h" +#include + +static const spl_builtin_t k_builtins[] = { + {"sizeof", SPL_BUILTIN_SIZE_OF, 1, 1, 0}, + {"bitsizeof", SPL_BUILTIN_BITSIZE_OF, 1, 1, 0}, + {"alignof", SPL_BUILTIN_ALIGN_OF, 1, 1, 0}, + {"offsetof", SPL_BUILTIN_OFFSET_OF, 2, 2, 0}, + {"field_count", SPL_BUILTIN_FIELD_COUNT, 1, 1, 0}, + {"dbg", SPL_BUILTIN_DBG, 0, -1, 1}, + {"assert", SPL_BUILTIN_ASSERT, 1, 1, 1}, + {"import", SPL_BUILTIN_IMPORT, 1, 1, 1}, +}; + +const spl_builtin_t *spl_builtin_lookup(const char *name) { + if (!name) + return NULL; + for (usize i = 0; i < sizeof(k_builtins) / sizeof(k_builtins[0]); i++) { + if (strcmp(k_builtins[i].name, name) == 0) + return &k_builtins[i]; + } + return NULL; +} + +int spl_builtin_count(void) { return (int)(sizeof(k_builtins) / sizeof(k_builtins[0])); } diff --git a/stage1/spl_builtin.h b/stage1/spl_builtin.h new file mode 100644 index 0000000..f280086 --- /dev/null +++ b/stage1/spl_builtin.h @@ -0,0 +1,43 @@ +/* spl_builtin.h — 内置函数集中注册表 + * + * @builtin 名称/类别/参数/返回类型的单一事实来源。 + * sema(类型推导)与 ast2ir(IR 发射)各自按 kind 分发实现。 + */ +#ifndef __SPL_BUILTIN_H__ +#define __SPL_BUILTIN_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + SPL_BUILTIN_SIZE_OF, /* @sizeof(T) -> usize */ + SPL_BUILTIN_BITSIZE_OF, /* @bitsizeof(T) -> usize */ + SPL_BUILTIN_ALIGN_OF, /* @alignof(T) -> usize */ + SPL_BUILTIN_OFFSET_OF, /* @offsetof(T, field) -> usize */ + SPL_BUILTIN_FIELD_COUNT, /* @field_count(T) -> usize */ + SPL_BUILTIN_DBG, /* @dbg(args...) -> void */ + SPL_BUILTIN_ASSERT, /* @assert(cond) -> void */ + SPL_BUILTIN_IMPORT, /* @import(path) -> 模块 (预留) */ + SPL_BUILTIN_COUNT +} spl_builtin_kind_t; + +typedef struct { + const char *name; + spl_builtin_kind_t kind; + int min_args; /* 参数个数下限 */ + int max_args; /* 参数个数上限,-1 = 不限 */ + int ret_is_void; /* 1 = void 返回 */ +} spl_builtin_t; + +/* 按名称查找内置;未注册返回 NULL */ +const spl_builtin_t *spl_builtin_lookup(const char *name); + +/* 内置总数 */ +int spl_builtin_count(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __SPL_BUILTIN_H__ */ diff --git a/stage1/spl_ir.c b/stage1/spl_ir.c index 4eb2d4e..d458a55 100644 --- a/stage1/spl_ir.c +++ b/stage1/spl_ir.c @@ -44,6 +44,7 @@ void spl_ir_drop(spl_ir_t *ir) { node_drop_vecs(&f->nodes.data[j]); vec_free(f->nodes); vec_free(f->labels); + vec_free(f->dbg_vars); } vec_free(ir->funcs); for (usize i = 0; i < ir->gdata.size; i++) @@ -56,6 +57,7 @@ spl_ir_func_ref_t spl_ir_alloc_fn(spl_ir_t *ir) { memset(&f, 0, sizeof f); vec_init(f.nodes); vec_init(f.labels); + vec_init(f.dbg_vars); vec_push(ir->funcs, f); return ir->funcs.size - 1; } @@ -504,3 +506,14 @@ void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty) { } } } + +const char *spl_ir_kind_name(spl_ir_kind_t kind) { + static const char *const names[] = { +#define X(a, b, c) #a, + SPL_IR_FN_TABLE +#undef X + }; + if ((usize)kind < sizeof(names) / sizeof(names[0])) + return names[kind]; + return "?"; +} diff --git a/stage1/spl_ir.h b/stage1/spl_ir.h index 5040caf..2776cee 100644 --- a/stage1/spl_ir.h +++ b/stage1/spl_ir.h @@ -91,6 +91,7 @@ typedef usize spl_ir_func_ref_t; /* 0 is error */ typedef struct { spl_ir_kind_t kind; + usize src_ref; /* AST 节点 ref(调试行号用,ast2ir 注解) */ union { struct { spl_type_id_t tid; @@ -236,12 +237,25 @@ typedef struct { }; } spl_ir_attr_t; typedef VEC(spl_ir_attr_t) spl_ir_attr_vec_t; + +/* 调试:函数内变量(名 → 内存位置)。alloca 节点或参数槽。 */ +typedef struct { + const char *name; /* 指向 AST 字符串,不拥有 */ + spl_ir_node_ref_t alloca; /* 非参数:alloca 节点 ref */ + spl_type_id_t tid; + int is_param; /* 参数则用 param_idx */ + usize param_idx; + usize offset; /* fp 字节偏移(LADDR imm 语义;ir2vm 填) */ +} spl_ir_dbg_var_t; +typedef VEC(spl_ir_dbg_var_t) spl_ir_dbg_var_vec_t; + typedef struct { const char *name; spl_ir_attr_t attr; spl_type_id_t fn_tid; spl_ir_node_vec_t nodes; spl_ir_node_ref_vec_t labels; + spl_ir_dbg_var_vec_t dbg_vars; /* 调试变量表(fp 偏移在 ir2vm 填) */ } spl_ir_func_t; typedef VEC(spl_ir_func_t) spl_ir_func_vec_t; @@ -261,5 +275,6 @@ spl_ir_node_t *spl_ir_node(spl_ir_t *ir, spl_ir_func_ref_t fn_id, spl_ir_node_re spl_ir_func_t *spl_ir_func(spl_ir_t *ir, spl_ir_func_ref_t fn_id); void spl_ir_dump(spl_ir_t *ir, const spl_type_t *ty); +const char *spl_ir_kind_name(spl_ir_kind_t kind); #endif /* __SPL_IR_H__ */ diff --git a/stage1/spl_ir2vm.c b/stage1/spl_ir2vm.c index a4b9bc7..c749b67 100644 --- a/stage1/spl_ir2vm.c +++ b/stage1/spl_ir2vm.c @@ -709,7 +709,16 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { emit_value(fc, n->arith.left); if (n->arith.right) emit_value(fc, n->arith.right); - emit_arith(fc, arith_op(n->kind, is_signed_type(ty, tid)), arith_tag(ty, tid)); + spl_opcode_t aop = arith_op(n->kind, is_signed_type(ty, tid)); + /* 浮点除法/取余:VM 的 DIV_S/REM_S 宏(DIV_REM_S)含 float 分支,DIV_U/REM_U 无 */ + spl_type_node_t *at = tn(ty, under(ty, tid)); + if (at && at->kind == SPL_TYPE_FLOAT) { + if (n->kind == SPL_IR_ARITH_DIV) + aop = SPL_DIV_S; + else if (n->kind == SPL_IR_ARITH_REM) + aop = SPL_REM_S; + } + emit_arith(fc, aop, arith_tag(ty, tid)); emit_store_vreg(fc, ref); return; } @@ -753,6 +762,11 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { emit_value(fc, n->cmp.a); emit_value(fc, n->cmp.b); spl_opcode_t op; + /* 浮点顺序比较:VM 的 CMP_U 无 float 分支,须走 CMP_S(SLT/SLE/SGT/SGE 含 float case) */ + int is_f = 0; + spl_type_node_t *ct = tn(ty, under(ty, tid)); + if (ct && ct->kind == SPL_TYPE_FLOAT) + is_f = 1; switch (n->kind) { case SPL_IR_CMP_EQ: op = SPL_EQ; @@ -761,16 +775,16 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { op = SPL_NE; break; case SPL_IR_CMP_LT: - op = is_signed_type(ty, tid) ? SPL_SLT : SPL_ULT; + op = (is_signed_type(ty, tid) || is_f) ? SPL_SLT : SPL_ULT; break; case SPL_IR_CMP_LE: - op = is_signed_type(ty, tid) ? SPL_SLE : SPL_ULE; + op = (is_signed_type(ty, tid) || is_f) ? SPL_SLE : SPL_ULE; break; case SPL_IR_CMP_GT: - op = is_signed_type(ty, tid) ? SPL_SGT : SPL_UGT; + op = (is_signed_type(ty, tid) || is_f) ? SPL_SGT : SPL_UGT; break; default: - op = is_signed_type(ty, tid) ? SPL_SGE : SPL_UGE; + op = (is_signed_type(ty, tid) || is_f) ? SPL_SGE : SPL_UGE; break; } emit_arith(fc, op, arith_tag(ty, tid)); @@ -845,8 +859,13 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { case SPL_IR_MEM_OFFSET: { emit_value(fc, n->mem_offset.ptr); emit_value(fc, n->mem_offset.offset); - emit_push(fc, type_size(ty, n->mem_offset.tid)); - emit_arith(fc, SPL_MUL, SPL_USIZE); + /* 指针运算(C 语义):*_(void 元素)看成整数,偏移即字节、不 scale; + * *T(非 void)偏移为元素索引,乘 sizeof(T)。 */ + spl_type_id_t ut = under(ty, n->mem_offset.tid); + if (!is_void(ty, ut)) { + emit_push(fc, type_size(ty, n->mem_offset.tid)); + emit_arith(fc, SPL_MUL, SPL_USIZE); + } emit_arith(fc, SPL_ADD, SPL_USIZE); emit_store_vreg(fc, ref); return; @@ -1032,14 +1051,18 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { vec_push(fc->c->fnfixes, fx); add_insn(fc, SPL_CALL, SPL_VOID, nargs); } + if (ret && !is_agg(ty, ret)) + emit_store_vreg(fc, ref); } else { - /* 间接调用:栈 [args, func_addr, nargs] CALLI */ - emit_value(fc, n->control_call.func); + /* 间接调用:栈 [args, nargs, func_addr] CALLI(VM: POP addr, POP nargs) + * 先 push 实参(上方循环),再 push nargs,最后 push func_addr */ emit_push(fc, nargs); + emit_value(fc, n->control_call.func); add_insn(fc, SPL_CALLI, SPL_VOID, 0); + /* 返回值留在栈顶,与直接调用一致:存入 vreg */ + if (ret && !is_agg(ty, ret)) + emit_store_vreg(fc, ref); } - if (ret && !is_agg(ty, ret)) - emit_store_vreg(fc, ref); return; } case SPL_IR_CONTROL_RET: { @@ -1065,10 +1088,12 @@ static void emit_node(fctx_t *fc, spl_ir_node_ref_t ref) { return; } case SPL_IR_CONTROL_UNREACHABLE: - case SPL_IR_CONTROL_TRAP: - diag(fc->c, fc->fid, ref, "control.unreachable/trap not implemented"); add_insn(fc, SPL_HALT, SPL_VOID, 0); return; + case SPL_IR_CONTROL_TRAP: + /* trap → halt 带非零退出码(assert 失败语义) */ + add_insn(fc, SPL_HALT, SPL_VOID, 1); + return; case SPL_IR_DBG_BREAKPOINT: add_insn(fc, SPL_BK, SPL_VOID, 0); return; @@ -1185,8 +1210,9 @@ static void gen_func(ctx_t *c, spl_ir_func_ref_t fid) { usize locals = 0; for (usize ref = 1; ref < fc.f->nodes.size; ref++) { spl_ir_node_t *rn = &fc.f->nodes.data[ref]; - if (!produces_value(rn->kind)) - continue; + /* 无条件分配(不按 produces_value 过滤):某些节点 produces_value 误报 0 但 + * 仍会被 emit_value 引用并 store_vreg(如聚合字段提取编译成的节点)。若跳过则 + * vreg_off 保持 calloc 的 0,多个节点共享槽 0 互相覆盖(指针偏移/写地址损坏根源)。 */ spl_type_id_t tid = 0; if (!needs_vreg_slot(fc.f, ref)) { /* 聚合值参数:分配 vreg(prologue 从参数区 memcpy 进来) */ @@ -1200,8 +1226,13 @@ static void gen_func(ctx_t *c, spl_ir_func_ref_t fid) { if (rn->kind == SPL_IR_MEM_ALLOCA) tid = rn->mem_alloc.tid; } - if (!tid) + if (!tid) { + /* tid 未解析(MEM_LOAD / BITCAST 未标 tid 等):占位一个 usize 槽, + * 否则 vreg_off 保持 0,多个节点共享槽 0 互相覆盖。 */ + fc.vreg_off[ref] = align_up(locals, 8); + locals = fc.vreg_off[ref] + 8; continue; + } usize sz = type_size(ty, tid); usize al = type_align(ty, tid); if (is_agg(ty, tid)) @@ -1211,7 +1242,9 @@ static void gen_func(ctx_t *c, spl_ir_func_ref_t fid) { locals += sz; } fc.temp_off = align_up(locals, 8); - locals = fc.temp_off + 8; /* mem.set 计数器槽 */ + /* 临时区(bytes):表达式/调用的 PUSH/POP 堆叠、store/bnz 的弹栈会临时压低 sp, + * 若无此区 sp 会降入 vreg 槽区覆盖尚未使用的 vreg(大数组构造等深表达式)。 */ + locals = fc.temp_off + 8 + 1024 * 8; fc.locals_bytes = locals; /* prologue:ALLOC + 聚合值参数 memcpy(参数区 → param vreg) */ diff --git a/stage1/spl_ir2vm.h b/stage1/spl_ir2vm.h index 0c417f0..f17451b 100644 --- a/stage1/spl_ir2vm.h +++ b/stage1/spl_ir2vm.h @@ -79,9 +79,17 @@ * ================================================================ */ +/* 调试映射:每函数 IR 节点 → 首条指令 ip(调试器显示当前 IR 节点用) */ +typedef struct { + spl_ir_func_ref_t fid; + VEC(usize) node_first_ip; /* 索引 = IR 节点 ref,值 = 该节点首指令绝对 ip */ +} spl_ir2vm_fdbg_t; +typedef VEC(spl_ir2vm_fdbg_t) spl_ir2vm_fdbg_vec_t; + typedef struct { const spl_ir_t *ir; const spl_type_t *type; + spl_ir2vm_fdbg_vec_t fdbg; /* ir2vm_run 后填充;splc0 -g 读取生成 debug 段 */ } spl_ir2vm_t; void spl_ir2vm_init(spl_ir2vm_t *ctx, const spl_ir_t *ir, const spl_type_t *type); diff --git a/stage1/spl_lexer.c b/stage1/spl_lexer.c index a9cfa91..2827bf0 100644 --- a/stage1/spl_lexer.c +++ b/stage1/spl_lexer.c @@ -270,7 +270,8 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { /* Hex literal */ offset += 2; col += 2; - while (offset < len && isxdigit((unsigned char)source[offset])) { + while (offset < len && + (isxdigit((unsigned char)source[offset]) || source[offset] == '_')) { offset++; col++; } @@ -280,7 +281,8 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { /* Binary literal */ offset += 2; col += 2; - while (offset < len && (source[offset] == '0' || source[offset] == '1')) { + while (offset < len && (source[offset] == '0' || source[offset] == '1' || + source[offset] == '_')) { offset++; col++; } @@ -290,7 +292,8 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { /* Octal literal */ offset += 2; col += 2; - while (offset < len && source[offset] >= '0' && source[offset] <= '7') { + while (offset < len && ((source[offset] >= '0' && source[offset] <= '7') || + source[offset] == '_')) { offset++; col++; } @@ -299,7 +302,8 @@ spl_tok_vec_t spl_lex(const char *source, const char *fname) { } /* Decimal integer or float */ - while (offset < len && isdigit((unsigned char)source[offset])) { + while (offset < len && + (isdigit((unsigned char)source[offset]) || source[offset] == '_')) { offset++; col++; } diff --git a/stage1/spl_sema.c b/stage1/spl_sema.c index 011d925..3491196 100644 --- a/stage1/spl_sema.c +++ b/stage1/spl_sema.c @@ -1,4 +1,4 @@ -// WRITE BY AI +// WRITE BY AI /* spl_sema.c SPL 语义分析 * * 两趟 AST 遍历(splc0 显式先 run 再 check): @@ -9,6 +9,7 @@ * 命名实体放 def_table,两张表 id 空间完全独立。 */ #include "spl_sema.h" +#include "spl_builtin.h" #include #include @@ -456,6 +457,13 @@ static void sema_const_decl(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_scope_ if (!n) return; register_binding(sema, n->const_decl.name, n->const_decl.type_expr, scope, agg_def, ref); + /* 标记 const:赋值检查拒绝写入 */ + spl_ast_node_t *nn = node_at(sema->ast, ref); + if (nn && nn->resolved_def_id) { + spl_def_node_t *d = def_at(sema, nn->resolved_def_id); + if (d) + d->var_def.is_const = 1; + } } /* fn 声明:建 fn type + FN_PARAMS def + 登记名字。不建 fn_scope(由 check 新建)。 @@ -580,6 +588,29 @@ static bool expr_is_int_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { } } +/* 浮点字面量(含负号前缀):允许拓宽/窄化到目标浮点类型 */ +static bool expr_is_float_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = node_at(sema->ast, ref); + if (!n || n->kind != SPL_AST_EXPR) + return false; + switch (n->expr.op) { + case SPL_AST_PRIMARY_EXPR: { + spl_ast_node_t *pn = node_at(sema->ast, n->expr.op_expr.left); + int k = pn && pn->kind == SPL_AST_EXPR ? (int)pn->primary_expr.kind : -1; + return k == SPL_AST_FLOAT; + } + case SPL_AST_PREFIX_EXPR: + return expr_is_float_literal(sema, n->expr.op_expr.left); + default: + return false; + } +} + +/* 字面量(整型或浮点):检查时允许类型拓宽 */ +static bool expr_is_literal(spl_sema_t *sema, spl_ast_node_ref_t ref) { + return expr_is_int_literal(sema, ref) || expr_is_float_literal(sema, ref); +} + /* 打开 SPL_TYPE_ID 绑定节点,返回真实类型(newtype 预留;当前无调用产生该节点) */ static spl_type_id_t underlying(spl_sema_t *sema, spl_type_id_t tid) { spl_type_node_t *t = type_node(sema, tid); @@ -650,6 +681,9 @@ static int type_compatible(spl_sema_t *sema, spl_type_id_t dst, spl_type_id_t sr /* 字面量值已隐含满足范围(检查时由调用方保证),此处允许拓宽 */ return 1; } + /* 浮点字面量可赋值到目标浮点(f64 字面量 → f32 变量,值可表示则允许) */ + if (is_literal && d->kind == SPL_TYPE_FLOAT && s->kind == SPL_TYPE_FLOAT) + return 1; /* isize/usize(机器字宽)与 i32 混合:比较/算术/传参可用(splc1 与旧测试事实标准) */ if (d->kind == SPL_TYPE_INT && s->kind == SPL_TYPE_INT) { int dbits = d->int_type.bits, sbits = s->int_type.bits; @@ -772,8 +806,8 @@ static spl_type_id_t infer_binary_cmp(spl_sema_t *sema, spl_ast_node_ref_t ref, return 0; } int w = 0; - if (type_compatible(sema, l, r, expr_is_int_literal(sema, e->expr.op_expr.right), &w) || - type_compatible(sema, r, l, expr_is_int_literal(sema, e->expr.op_expr.left), &w)) { + if (type_compatible(sema, l, r, expr_is_literal(sema, e->expr.op_expr.right), &w) || + type_compatible(sema, r, l, expr_is_literal(sema, e->expr.op_expr.left), &w)) { return spl_type_bool(&sema->type); } sema_error(sema, ref, "type mismatch in comparison"); @@ -919,7 +953,7 @@ static spl_type_id_t infer_agg_init(spl_sema_t *sema, spl_ast_node_ref_t ref, sp int w = 0; if (!expr_is_null_literal(sema, item->aggregate_init_item.expr) && et && !type_compatible(sema, mt, et, - expr_is_int_literal(sema, item->aggregate_init_item.expr), &w)) { + expr_is_literal(sema, item->aggregate_init_item.expr), &w)) { sema_error(sema, iref, "field type mismatch in aggregate literal"); } } @@ -942,8 +976,7 @@ static spl_type_id_t infer_array_lit(spl_sema_t *sema, spl_ast_node_ref_t ref, s int w = 0; if (!type_compatible( sema, elem, et, - expr_is_int_literal(sema, pn->primary_expr.array_lit_expr.expr_list.data[i]), - &w)) { + expr_is_literal(sema, pn->primary_expr.array_lit_expr.expr_list.data[i]), &w)) { sema_error(sema, pn->primary_expr.array_lit_expr.expr_list.data[i], "element type mismatch in array literal"); } @@ -1017,16 +1050,35 @@ static spl_type_id_t infer_primary(spl_sema_t *sema, spl_ast_node_ref_t ref, spl return infer_expr(sema, pn->primary_expr.expr); case SPL_AST_ARRAY_LIT: return infer_array_lit(sema, ref, n); - case SPL_AST_BUILTIN_EXPR: - /* 内置调用:先推断实参,类型按名称约定 */ - for (usize i = 0; i < pn->primary_expr.builtin_expr.expr_list.size; i++) + case SPL_AST_BUILTIN_EXPR: { + /* 内置调用:类型按注册表约定,参数按需推断(offsetof 字段名参数非表达式) */ + const spl_builtin_t *bi = spl_builtin_lookup(pn->primary_expr.builtin_expr.ident); + if (!bi) { + sema_error(sema, ref, "unknown builtin"); + return 0; + } + usize nargs = pn->primary_expr.builtin_expr.expr_list.size; + if (nargs < (usize)bi->min_args || (bi->max_args >= 0 && nargs > (usize)bi->max_args)) { + char buf[96]; + snprintf(buf, sizeof buf, "builtin @%s: arg count mismatch", bi->name); + sema_error(sema, ref, buf); + return 0; + } + for (usize i = 0; i < nargs; i++) { + /* offsetof 第二参数为字段标识符,不按表达式推断 */ + if (bi->kind == SPL_BUILTIN_OFFSET_OF && i == 1) + continue; infer_expr(sema, pn->primary_expr.builtin_expr.expr_list.data[i]); - if (strcmp(pn->primary_expr.builtin_expr.ident, "sizeof") == 0) - return spl_type_int(&sema->type, sizeof(usize) * 8, 0); - if (strcmp(pn->primary_expr.builtin_expr.ident, "dbg") == 0 || - strcmp(pn->primary_expr.builtin_expr.ident, "assert") == 0) + } + if (bi->ret_is_void) return spl_type_void(&sema->type); - return spl_type_void(&sema->type); + if (bi->kind == SPL_BUILTIN_SIZE_OF || bi->kind == SPL_BUILTIN_BITSIZE_OF || + bi->kind == SPL_BUILTIN_ALIGN_OF || bi->kind == SPL_BUILTIN_OFFSET_OF || + bi->kind == SPL_BUILTIN_FIELD_COUNT) + return spl_type_int(&sema->type, sizeof(usize) * 8, 0); + sema_error(sema, ref, "unsupported builtin"); + return 0; + } case SPL_AST_BLOCK_EXPR: { /* 块表达式:有独立 scope;逐语句检查,返回末尾表达式类型(无则 void) */ spl_ast_node_ref_vec_t *items = &pn->primary_expr.block_expr; @@ -1223,7 +1275,7 @@ static spl_type_id_t infer_postfix(spl_sema_t *sema, spl_ast_node_ref_t ref, spl int w = 0; if (!expr_is_null_literal(sema, args->data[i]) && at && !type_compatible(sema, t->fn_type.params.data[i], at, - expr_is_int_literal(sema, args->data[i]), &w)) { + expr_is_literal(sema, args->data[i]), &w)) { sema_error(sema, args->data[i], "argument type mismatch"); } } @@ -1299,10 +1351,24 @@ static spl_type_id_t infer_expr(spl_sema_t *sema, spl_ast_node_ref_t ref) { sema_error(sema, ref, "bad assignment"); return 0; } + /* 不可写检查:赋值目标为 const 变量时拒绝 */ + { + spl_ast_node_t *lhs = node_at(sema->ast, n->expr.op_expr.left); + if (lhs && lhs->kind == SPL_AST_EXPR && lhs->expr.op == SPL_AST_PRIMARY_EXPR) { + spl_ast_node_t *lpn = node_at(sema->ast, lhs->expr.op_expr.left); + if (lpn && lpn->kind == SPL_AST_EXPR && + lpn->primary_expr.kind == SPL_AST_IDENT && lpn->resolved_def_id) { + spl_def_node_t *ld = def_at(sema, lpn->resolved_def_id); + if (ld && ld->kind == SPL_DEF_VAR && ld->var_def.is_const) { + sema_error(sema, ref, "cannot assign to const"); + return 0; + } + } + } + } int w = 0; if (!expr_is_null_literal(sema, n->expr.op_expr.right) && - !type_compatible(sema, l, r, expr_is_int_literal(sema, n->expr.op_expr.right), - &w)) { + !type_compatible(sema, l, r, expr_is_literal(sema, n->expr.op_expr.right), &w)) { sema_error(sema, ref, "assignment type mismatch"); return 0; } @@ -1361,7 +1427,7 @@ static void check_var_init(spl_sema_t *sema, spl_ast_node_ref_t ref, const char if (dt) { int w = 0; if (!expr_is_null_literal(sema, init_expr) && it && - !type_compatible(sema, dt, it, expr_is_int_literal(sema, init_expr), &w)) { + !type_compatible(sema, dt, it, expr_is_literal(sema, init_expr), &w)) { sema_error(sema, ref, "initializer type mismatch"); } else if (w) { sema_warn(sema, ref, "pointer conversion involves wildcard"); @@ -1427,7 +1493,7 @@ static spl_type_id_t infer_agg_init_with_type(spl_sema_t *sema, spl_ast_node_ref int w = 0; if (!expr_is_null_literal(sema, item->aggregate_init_item.expr) && et && !type_compatible(sema, mt, et, - expr_is_int_literal(sema, item->aggregate_init_item.expr), &w)) { + expr_is_literal(sema, item->aggregate_init_item.expr), &w)) { sema_error(sema, iref, "field type mismatch in aggregate literal"); } } @@ -1492,6 +1558,33 @@ static void check_match(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t sema_error(sema, ref, "match: arm pattern/body count mismatch"); return; } + /* 穷举检查:enum 必须覆盖所有变体,或含通配 _(含表达式的整数 match 免检) */ + { + spl_def_id_t adef = def_for_type(sema, mtype); + spl_def_node_t *ad = adef ? &sema->type.def_table.data[adef] : NULL; + int is_enum_agg = ad && ad->kind == SPL_DEF_AGG; + if (is_enum_agg) { + int has_wild = 0; + usize covered = 0; + for (usize i = 0; i < arms->size; i++) { + spl_ast_node_t *pk = node_at(sema->ast, arms->data[i]); + if (!pk) + continue; + /* _ 通配:ident 与 expr 均为空 */ + if (!pk->packed_expr.ident && !pk->packed_expr.expr) { + has_wild = 1; + break; + } + if (pk->packed_expr.ident) { + /* 变体被覆盖:匹配臂中出现的合法变体计数 */ + if (agg_member_type(sema, mtype, pk->packed_expr.ident)) + covered++; + } + } + if (!has_wild && covered < ad->agg_def.size) + sema_error(sema, ref, "match must be exhaustive"); + } + } for (usize i = 0; i < arms->size; i++) { spl_ast_node_t *pk = node_at(sema->ast, arms->data[i]); if (!pk) @@ -1517,7 +1610,7 @@ static void check_match(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_ast_node_t spl_type_id_t et = infer_expr(sema, pk->packed_expr.expr); int w = 0; if (is_int_tid(sema, mtype) && et && - !type_compatible(sema, mtype, et, expr_is_int_literal(sema, pk->packed_expr.expr), + !type_compatible(sema, mtype, et, expr_is_literal(sema, pk->packed_expr.expr), &w)) { sema_error(sema, pk->packed_expr.expr, "match arm pattern type mismatch"); } @@ -1625,7 +1718,7 @@ static void check_stmt(spl_sema_t *sema, spl_ast_node_ref_t ref, spl_sema_ctx_t if (ctx.ret) { if (!expr_is_null_literal(sema, rd->block_item.ret_statement.expr) && et && !type_compatible(sema, ctx.ret, et, - expr_is_int_literal(sema, rd->block_item.ret_statement.expr), + expr_is_literal(sema, rd->block_item.ret_statement.expr), NULL)) { sema_error(sema, rd->block_item.ret_statement.expr, "ret type mismatch"); } @@ -1668,9 +1761,17 @@ static void check_block(spl_sema_t *sema, spl_ast_node_ref_vec_t *block, spl_sco b->block_item.var_decl); } else if (b->block_item.kind == SPL_AST_CONSTDECL) { spl_ast_node_t *cd = node_at(sema->ast, b->block_item.const_decl); - if (cd) + if (cd) { register_binding(sema, cd->const_decl.name, cd->const_decl.type_expr, scope, 0, b->block_item.const_decl); + /* 标记 const:赋值检查拒绝写入 */ + spl_ast_node_t *cn = node_at(sema->ast, b->block_item.const_decl); + if (cn && cn->resolved_def_id) { + spl_def_node_t *cdd = def_at(sema, cn->resolved_def_id); + if (cdd) + cdd->var_def.is_const = 1; + } + } } else if (b->block_item.kind == SPL_AST_TYPEDECL) { spl_ast_node_t *td = node_at(sema->ast, b->block_item.type_decl); if (td) @@ -1826,6 +1927,9 @@ void spl_sema_run(spl_sema_t *sema) { sema_var_decl(sema, mref, sema->root_scope, sema->root_def); else if (m->kind == SPL_AST_CONST_DECL) sema_const_decl(sema, mref, sema->root_scope, sema->root_def); + else if (m->kind == SPL_AST_MEMBER_DECL && m->member_decl.name) + register_binding(sema, m->member_decl.name, m->member_decl.type_expr, sema->root_scope, + sema->root_def, mref); } sema->current_scope = sema->root_scope; } diff --git a/stage1/spl_type.h b/stage1/spl_type.h index 237489c..830bb02 100644 --- a/stage1/spl_type.h +++ b/stage1/spl_type.h @@ -58,6 +58,7 @@ typedef struct { spl_def_id_t def_id; spl_type_id_t type_id; usize scope_id; + int is_const; /* var_def 是否为 const 声明(只读) */ } spl_var_def_t; typedef VEC(spl_var_def_t) spl_var_def_vec_t; diff --git a/stage1/splc0.c b/stage1/splc0.c index 0e3d5ae..d1486be 100644 --- a/stage1/splc0.c +++ b/stage1/splc0.c @@ -168,7 +168,50 @@ static int cmd_dump(const char *flags, const char *path) { return 0; } -static int compile_spl(const char *src, const char *fname, const char *outpath) { +static spl_ast_node_t *ast_node_at(spl_ast_t *ast, spl_ast_node_ref_t ref) { + if (ref == 0 || ref >= ast->buckets.size) + return NULL; + return &ast->buckets.data[ref]; +} + +static int ast_line(spl_ast_t *ast, spl_ast_node_ref_t ref) { + spl_ast_node_t *n = ast_node_at(ast, ref); + return n ? n->loc.line : 0; +} + +/* -g:在 .sir 尾部追加 debug 段(文本:IR 行 + VAR 行),spl_cli -g 读取 */ +static void gen_debug_map(const char *outpath, spl_ast_t *ast, const spl_ir_t *ir, + const spl_ir2vm_t *ir2vm) { + FILE *f = fopen(outpath, "ab"); + if (!f) + return; + fprintf(f, "SPLDBG\n"); + for (usize i = 0; i < ir2vm->fdbg.size; i++) { + const spl_ir2vm_fdbg_t *fd = &ir2vm->fdbg.data[i]; + if (fd->fid >= ir->funcs.size) + continue; + const spl_ir_func_t *fn = &ir->funcs.data[fd->fid]; + const char *fname = fn->name ? fn->name : "?"; + for (usize ref = 1; ref < fd->node_first_ip.size; ref++) { + usize ip = fd->node_first_ip.data[ref]; + if (ip == (usize)-1) + continue; + const spl_ir_node_t *n = &fn->nodes.data[ref]; + fprintf(f, "IR %zu %zu %d %s\n", ip, ref, ast_line(ast, n->src_ref), + spl_ir_kind_name(n->kind)); + } + for (usize j = 0; j < fn->dbg_vars.size; j++) { + const spl_ir_dbg_var_t *dv = &fn->dbg_vars.data[j]; + if (!dv->name) + continue; + fprintf(f, "VAR %s %s %zu %zu %d\n", fname, dv->name, dv->offset, dv->tid, + dv->is_param); + } + } + fclose(f); +} + +static int compile_spl(const char *src, const char *fname, const char *outpath, int gen_debug) { spl_tok_vec_t toks = spl_lex(src, fname); spl_ast_t ast; spl_ast_init(&ast, &toks); @@ -203,6 +246,8 @@ static int compile_spl(const char *src, const char *fname, const char *outpath) spl_ir2vm_t ir2vm; spl_ir2vm_init(&ir2vm, &a2ir.ir, &sema.type); int rc = spl_ir2vm_run(&ir2vm, outpath); + if (gen_debug && rc == 0) + gen_debug_map(outpath, &ast, &a2ir.ir, &ir2vm); spl_ir2vm_drop(&ir2vm); spl_ast2ir_drop(&a2ir); spl_sema_drop(&sema); @@ -212,36 +257,45 @@ static int compile_spl(const char *src, const char *fname, const char *outpath) int main(int argc, char **argv) { if (argc < 2) { - LOG_FATAL("Usage: splc0 [--dump ] [out]\n"); + LOG_FATAL("Usage: splc0 [--dump ] [out]"); return 1; } if (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0) { - LOG_INFO("splc0 compile (.spl -> .sir, 阶段 B)\n"); - LOG_INFO("splc0 --dump dump: tokens,ast,sema,ir,all\n"); + LOG_INFO("splc0 compile (.spl -> .sir, stage B)"); + LOG_INFO("splc0 --dump dump: tokens,ast,sema,ir,all"); return 0; } int argi = 1; if (argi >= argc) { - LOG_FATAL("Usage: splc0 [--dump ] [out]\n"); + LOG_FATAL("Usage: splc0 [--dump ] [out]"); return 1; } if (strcmp(argv[argi], "--dump") == 0) { if (argc < argi + 3) { - LOG_INFO("splc0: --dump need \n"); + LOG_INFO("splc0: --dump need "); return 1; } return cmd_dump(argv[argi + 1], argv[argi + 2]); } - /* splc0 */ + /* splc0 [-g] */ if (argc < argi + 2) { - LOG_FATAL("Usage: splc0 or splc0 --dump \n"); + LOG_FATAL("Usage: splc0 [-g] or splc0 --dump \n"); + return 1; + } + int gen_debug = 0; + if (strcmp(argv[argi], "-g") == 0) { + gen_debug = 1; + argi++; + } + if (argc < argi + 2) { + LOG_FATAL("Usage: splc0 [-g] or splc0 --dump \n"); return 1; } long len; char *src = read_file(argv[argi], &len); if (!src) return 1; - int rc = compile_spl(src, argv[argi], argv[argi + 1]); + int rc = compile_spl(src, argv[argi], argv[argi + 1], gen_debug); free(src); return rc; } diff --git a/stage1/splc_cli.c b/stage1/splc_cli.c deleted file mode 100644 index 1efbc2f..0000000 --- a/stage1/splc_cli.c +++ /dev/null @@ -1,68 +0,0 @@ -/* spc_vm.c launcher for stage 1 */ - -#include "../stage0/spl_mcode.h" -#include "../stage0/spl_syscall.h" -#include "../stage0/spl_vm.h" - -#include -#include - -int main(int argc, const char **argv) { - int argi = 1; - - /* Parse flags: --entry , --trace, -d */ - const char *entry = "main"; - int trace = 0; - int debug_addr = 0; - for (int i = argi; i < argc; i += 1) { - if (strcmp(argv[i], "--entry") == 0 && i + 1 < argc) { - entry = argv[++i]; - } else if (strcmp(argv[i], "--trace") == 0) { - trace = 1; - } else if (strcmp(argv[i], "-d") == 0) { - debug_addr = 1; - } else if (argv[i][0] != '-') { - argi = i; - break; - } - } - - if (argi >= argc) { - fprintf(stderr, "Usage: spc_vm [-d] [--trace] [args...]\n"); - return 1; - } - - const char *path = argv[argi++]; - const char **spl_argv = argv + (argi - 1); - int spl_argc = (int)(argc - (argi - 1)); - - spl_prog_t prog; - if (spl_prog_load_from_file(path, &prog) != 0) { - fprintf(stderr, "spc_vm: cannot load '%s'\n", path); - return 1; - } - - spl_syscall_register(&prog); - - spl_vm_t vm; - spl_vm_init(&vm); - if (spl_vm_load_prog(&vm, &prog) != 0) { - fprintf(stderr, "vm: prog '%s' not found\n", entry); - spl_prog_drop(&prog); - return 1; - } - if (spl_vm_prepare(&vm, entry, spl_argc, spl_argv, NULL) != 0) { - fprintf(stderr, "vm: entry point '%s' not found\n", entry); - spl_prog_drop(&prog); - return 1; - } - spl_vm_set_trace(&vm, trace); - if (debug_addr) - spl_vm_set_debug(&vm, 1); - - int ret = spl_vm_run_until(&vm, 0); - spl_vm_drop(&vm); - spl_prog_drop(&prog); - - return (int)vm.exit_code; -} diff --git a/stage1/test00_basic.spl b/stage1/test00_basic.spl deleted file mode 100644 index d235944..0000000 --- a/stage1/test00_basic.spl +++ /dev/null @@ -1,8 +0,0 @@ -/* ===== 模块1:核心基础 ===== - * test00_basic — 最小程序 / 返回码 - * 难度:1/5 - * 验证点:函数定义、整型返回、ret 语句 - */ -fn main() i32 { - ret 0; -} diff --git a/stage1/test01_literals.spl b/stage1/test01_literals.spl deleted file mode 100644 index 70048f2..0000000 --- a/stage1/test01_literals.spl +++ /dev/null @@ -1,43 +0,0 @@ -/* ===== 模块1:核心基础 ===== - * test01_literals — 全部字面量形式 - * 难度:1/5 - * 验证点:十进制/十六进制/二进制/八进制整数、 - * 字符字面量、字符串字面量、布尔字面量、null - */ -fn main() i32 { - /* 整数:十进制 */ - var a: i32 = 42; - if a != 42 { ret 1; } - - /* 整数:十六进制 */ - var b: i32 = 0xFF; - if b != 255 { ret 2; } - - /* 整数:二进制 */ - var c: i32 = 0b1010; - if c != 10 { ret 3; } - - /* 整数:八进制 */ - var d: i32 = 0o77; - if d != 63 { ret 4; } - - /* 字符字面量 */ - var ch: i32 = 'A'; - if ch != 65 { ret 5; } - - /* 字符转义 */ - var nl: i32 = '\n'; - if nl != 10 { ret 6; } - - /* 布尔字面量 */ - var t: bool = true; - if !t { ret 7; } - var f: bool = false; - if f { ret 8; } - - /* null 指针 */ - var np: *i32 = null; - if np != null { ret 9; } - - ret 0; -} diff --git a/stage1/test02_variables.spl b/stage1/test02_variables.spl deleted file mode 100644 index feba842..0000000 --- a/stage1/test02_variables.spl +++ /dev/null @@ -1,51 +0,0 @@ -/* ===== 模块1:核心基础 ===== - * test02_variables — 变量与常量声明 - * 难度:1/5 - * 验证点:var 声明 + 类型注解、var 声明 + 初始化、 - * const 声明、var := 短声明、const := 短声明 - */ -fn main() i32 { - /* var 带类型注解与初始化 */ - var a: i32 = 10; - if a != 10 { ret 1; } - - /* var 先声明后赋值 */ - var b: i32; - b = 20; - if b != 20 { ret 2; } - - /* const 声明 */ - const c: i32 = 30; - if c != 30 { ret 3; } - - /* var := 短声明(类型推断) */ - var d := 40; - if d != 40 { ret 4; } - - /* const := 短声明 */ - const e := 50; - if e != 50 { ret 5; } - - /* 多类型变量 */ - var i8v: i8 = 127; - if i8v != 127 { ret 6; } - - var u8v: u8 = 255; - if u8v != 255 { ret 7; } - - var i16v: i16 = 32767; - if i16v != 32767 { ret 8; } - - var u16v: u16 = 65535; - if u16v != 65535 { ret 9; } - - var u32v: u32 = 4294967295; - if u32v != 4294967295 { ret 10; } - - /* 指针类型变量 */ - var x: i32 = 100; - var p: *i32 = &x; - if p == null { ret 11; } - - ret 0; -} diff --git a/stage1/test03_arithmetic.spl b/stage1/test03_arithmetic.spl deleted file mode 100644 index e590599..0000000 --- a/stage1/test03_arithmetic.spl +++ /dev/null @@ -1,56 +0,0 @@ -/* ===== 模块2:表达式 ===== - * test03_arithmetic — 算术运算 - * 难度:1/5 - * 验证点:加、减、乘、除、取模、负数、混合运算优先级 - */ -fn main() i32 { - /* 加法 */ - var a := 12 + 34; - if a != 46 { ret 1; } - - /* 减法 */ - var b := 100 - 23; - if b != 77 { ret 2; } - - /* 乘法 */ - var c := 7 * 8; - if c != 56 { ret 3; } - - /* 除法 */ - var d := 100 / 3; - if d != 33 { ret 4; } - - /* 取模 */ - var e := 100 % 3; - if e != 1 { ret 5; } - - /* 负数 */ - var f := -5; - if f != -5 { ret 6; } - - /* 负数运算 */ - var g := -10 + 3; - if g != -7 { ret 7; } - - /* 运算优先级:乘优先于加 */ - var h := 2 + 3 * 4; - if h != 14 { ret 8; } - - /* 括号改变优先级 */ - var i := (2 + 3) * 4; - if i != 20 { ret 9; } - - /* 连续运算 */ - var j := 1 + 2 + 3 + 4 + 5; - if j != 15 { ret 10; } - - /* 混合运算 */ - var k := 10 * 2 - 8 / 4; - if k != 18 { ret 11; } - - /* 负数取模 */ - var l := -7 % 3; - if l != -1 { ret 12; } - - ret 0; -} diff --git a/stage1/test04_operators.spl b/stage1/test04_operators.spl deleted file mode 100644 index 3e55fd7..0000000 --- a/stage1/test04_operators.spl +++ /dev/null @@ -1,66 +0,0 @@ -/* ===== 模块2:表达式 ===== - * test04_operators — 比较/逻辑/位运算 + 短路求值 - * 难度:2/5 - * 验证点:== != < <= > >=、&& || !、& | ^ ~ << >>、&&/|| 短路 - */ -fn main() i32 { - /* ---- 比较运算 ---- */ - if (1 < 2) {} else { ret 1; } - if (3 > 1) {} else { ret 2; } - if (2 == 2) {} else { ret 3; } - if (2 != 3) {} else { ret 4; } - if (2 <= 2) {} else { ret 5; } - if (2 <= 3) {} else { ret 6; } - if (3 >= 3) {} else { ret 7; } - if (3 >= 2) {} else { ret 8; } - - /* 比较结果为 0/1 */ - var eq := (42 == 42); - if !eq { ret 9; } - var ne := (42 == 43); - if ne { ret 10; } - var lt := (5 < 10); - if !lt { ret 11; } - - /* ---- 逻辑运算 ---- */ - if (true) {} else { ret 12; } - if (!false) {} else { ret 13; } - if (true && true) {} else { ret 14; } - if (false || true) {} else { ret 15; } - - /* 逻辑非 */ - var not_t := !true; - if not_t { ret 16; } - var not_f := !false; - if !not_f { ret 17; } - - // /* ---- 短路求值 ---- */ - // var short1 := 0; - // var short2 := 0; - // if (false && { short1 = 1; true; }) {} else {} - // if short1 != 0 { ret 18; } /* 右侧未执行 */ - - /* ---- 位运算 ---- */ - var band := 0xFF & 0x0F; - if band != 0x0F { ret 19; } - - var bor := 0xF0 | 0x0F; - if bor != 0xFF { ret 20; } - - var bxor := 0xFF ^ 0x0F; - if bxor != 0xF0 { ret 21; } - - var bnot := ~0xFF; - /* ~0xFF 在 32 位下 = 0xFFFFFF00,即 -256 */ - if bnot != -256 { ret 22; } - - /* 左移 */ - var shl := 1 << 3; - if shl != 8 { ret 23; } - - /* 右移 */ - var shr := 16 >> 2; - if shr != 4 { ret 24; } - - ret 0; -} diff --git a/stage1/test05_control.spl b/stage1/test05_control.spl deleted file mode 100644 index 9133848..0000000 --- a/stage1/test05_control.spl +++ /dev/null @@ -1,79 +0,0 @@ -/* ===== 模块3:控制流 ===== - * test05_control — 分支与循环 - * 难度:2/5 - * 验证点:if/else、while、loop、break、continue - */ -fn main() i32 { - /* ---- if/else ---- */ - var x: i32 = 10; - if x > 5 { - x = 0; - } else { - x = 1; - } - if x != 0 { ret 1; } - - /* else 分支 */ - var y: i32 = 1; - if y > 5 { - y = 10; - } else { - y = 20; - } - if y != 20 { ret 2; } - - /* if 不带 else */ - var z: i32 = 0; - if z == 0 { - z = 99; - } - if z != 99 { ret 3; } - - /* ---- while ---- */ - var i: i32 = 0; - while i < 5 { - i = i + 1; - } - if i != 5 { ret 4; } - - /* while 条件为 false */ - var j: i32 = 0; - while j > 0 { - j = j + 1; - } - if j != 0 { ret 5; } - - /* ---- loop / break ---- */ - var k: i32 = 0; - loop { - k = k + 1; - if k >= 3 { break; } - } - if k != 3 { ret 6; } - - /* ---- continue ---- */ - var n: i32 = 0; - var m: i32 = 0; - while n < 5 { - n = n + 1; - if n == 3 { continue; } - m = m + 1; - } - if n != 5 { ret 7; } - if m != 4 { ret 8; } - - /* ---- 嵌套控制流 ---- */ - var total: i32 = 0; - var p: i32 = 0; - while p < 3 { - var q: i32 = 0; - while q < 4 { - total = total + 1; - q = q + 1; - } - p = p + 1; - } - if total != 12 { ret 9; } - - ret 0; -} diff --git a/stage1/test06_for.spl b/stage1/test06_for.spl deleted file mode 100644 index 20d575d..0000000 --- a/stage1/test06_for.spl +++ /dev/null @@ -1,48 +0,0 @@ -/* ===== 模块3:控制流 ===== - * test06_for — for 区间循环 - * 难度:2/5 - * 验证点:for begin..end as i、for slice as val、for slice,0.. as val,idx - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; - -fn main() i32 { - /* for 数值区间:for 0..N as i */ - var sum: i32 = 0; - for 0..5 as i { - sum = sum + i; - } - /* 0+1+2+3+4 = 10 */ - if sum != 10 { ret 1; } - - /* for 数值区间:非 0 起始 */ - var sum2: i32 = 0; - for 3..7 as i { - sum2 = sum2 + i; - } - /* 3+4+5+6 = 18 */ - if sum2 != 18 { ret 2; } - - /* for 遍历切片 */ - var arr: [4]i32 = [4]i32{10, 20, 30, 40}; - var sl: []i32 = arr[0..]; - var total: i32 = 0; - for sl as val { - total = total + val; - } - /* 10+20+30+40 = 100 */ - if total != 100 { ret 3; } - - /* for 遍历切片 + 索引 */ - var arr2: [3]i32 = [3]i32{100, 200, 300}; - var sl2: []i32 = arr2[0..]; - var sum_val: i32 = 0; - var sum_idx: i32 = 0; - for sl2, 0.. as val, idx { - sum_val = sum_val + val; - sum_idx = sum_idx + idx; - } - if sum_val != 600 { ret 4; } - if sum_idx != 3 { ret 5; } - - ret 0; -} diff --git a/stage1/test07_pointers.spl b/stage1/test07_pointers.spl deleted file mode 100644 index 9cff38e..0000000 --- a/stage1/test07_pointers.spl +++ /dev/null @@ -1,64 +0,0 @@ -/* ===== 模块4:指针 ===== - * test07_pointers — 指针操作 - * 难度:2/5 - * 验证点:& 取地址、* 解引用、null 空指针、指针自动解引用(->)、.* 后缀解引用 - */ -fn inc(ptr: *i32) void { - *ptr = *ptr + 1; -} - -fn main() i32 { - /* ---- & 取地址和 * 解引用 ---- */ - var x: i32 = 42; - var p: *i32 = &x; - var v := p.*; - if v != 42 { ret 1; } - - /* 通过指针修改 */ - p.* = 99; - if x != 99 { ret 2; } - - /* 指针作为函数参数 */ - var y: i32 = 5; - inc(&y); - if y != 6 { ret 3; } - - /* ---- null 空指针 ---- */ - var np: *i32 = null; - if np != null { ret 4; } - if np == null {} else { ret 5; } - - /* ---- 指针自动解引用(ptr.field 相当于 ptr->field) ---- */ - type Point = struct { - a: i32, - b: i32, - }; - - var pt: Point; - pt.a = 10; - pt.b = 20; - var pp: *Point = &pt; - if pp.a != 10 { ret 6; } - if pp.b != 20 { ret 7; } - - /* 通过指针修改字段 */ - pp.a = 30; - if pt.a != 30 { ret 8; } - - /* ---- 指向数组元素的指针 ---- */ - var buf: [4]i32 = [4]i32{1, 2, 3, 4}; - // @dbg(); /* 数组初始化后的栈状态 */ - var elem_ptr: *i32 = &buf[0]; - // @dbg(); /* &buf[0] 之后:栈上应有指针值 */ - var loaded := elem_ptr.*; - // @dbg(); /* 解引用后:loaded 值 */ - if loaded != 1 { ret 9; } - - elem_ptr = &buf[1]; - // @dbg(); /* &buf[1] 之后 */ - var loaded2 := elem_ptr.*; - // @dbg(); /* 解引用后:loaded2 值 */ - if loaded2 != 2 { ret 10; } - - ret 0; -} diff --git a/stage1/test08_arrays.spl b/stage1/test08_arrays.spl deleted file mode 100644 index 0141da6..0000000 --- a/stage1/test08_arrays.spl +++ /dev/null @@ -1,38 +0,0 @@ -/* ===== 模块5:复合类型 ===== - * test08_arrays — 数组 - * 难度:2/5 - * 验证点:数组字面量 [N]T{...}、数组索引、数组元素修改 - */ -fn main() i32 { - /* 数组字面量 */ - var arr: [3]i32 = [3]i32{1, 2, 3}; - if arr[0] != 1 { ret 1; } - if arr[1] != 2 { ret 2; } - if arr[2] != 3 { ret 3; } - - /* 数组元素修改 */ - arr[1] = 99; - if arr[1] != 99 { ret 4; } - - /* 数组求和 */ - var nums: [5]i32 = [5]i32{10, 20, 30, 40, 50}; - var sum: i32 = 0; - sum = sum + nums[0]; - sum = sum + nums[1]; - sum = sum + nums[2]; - sum = sum + nums[3]; - sum = sum + nums[4]; - if sum != 150 { ret 5; } - - /* 数组通过循环访问(while) */ - var vals: [4]i32 = [4]i32{2, 4, 6, 8}; - var i: i32 = 0; - var s: i32 = 0; - while i < 4 { - s = s + vals[i]; - i = i + 1; - } - if s != 20 { ret 6; } - - ret 0; -} diff --git a/stage1/test09_slices.spl b/stage1/test09_slices.spl deleted file mode 100644 index cd2fe2b..0000000 --- a/stage1/test09_slices.spl +++ /dev/null @@ -1,43 +0,0 @@ -/* ===== 模块5:复合类型 ===== - * test09_slices — 切片 - * 难度:2/5 - * 验证点:arr[begin..end] 创建切片、arr[begin..] 到末尾、 - * 切片索引访问、slice.len、slice.ptr - */ -fn main() i32 { - /* 从数组创建切片 */ - var arr: [5]i32 = [5]i32{10, 20, 30, 40, 50}; - var slice: []i32 = arr[1..4]; - - /* 切片长度 */ - if slice.len != 3 { ret 1; } - - /* 切片元素访问 */ - if slice[0] != 20 { ret 2; } - if slice[1] != 30 { ret 3; } - if slice[2] != 40 { ret 4; } - - /* 省略结束值:arr[begin..] */ - var full: []i32 = arr[0..]; - if full.len != 5 { ret 5; } - if full[0] != 10 { ret 6; } - if full[4] != 50 { ret 7; } - - /* 从开头到中间 */ - var head: []i32 = arr[0..3]; - if head.len != 3 { ret 8; } - if head[0] != 10 { ret 9; } - - /* 切片遍历(配合 for)*/ - var nums: [3]i32 = [3]i32{100, 200, 300}; - var sl: []i32 = nums[0..]; - var total: i32 = 0; - var i: i32 = 0; - while i < sl.len { - total = total + sl[i]; - i = i + 1; - } - if total != 600 { ret 10; } - - ret 0; -} diff --git a/stage1/test10_struct.spl b/stage1/test10_struct.spl deleted file mode 100644 index dc32b52..0000000 --- a/stage1/test10_struct.spl +++ /dev/null @@ -1,215 +0,0 @@ -/* ===== 模块5:复合类型 ===== - * test10_struct — 结构体 - * 难度:2/5 - * 验证点:struct 定义、字段访问、内联 type、嵌套结构体 - */ -type Pair = struct { - a: i32, - b: i32, -} - -type Three = struct { - a: i64, - b: i64, - c: i64, -} - -type Tag = enum { - Unknown, - BlockComment, - LineComment, - Ident, - Number, -} - -type Token = struct { - loc_start: i32, - loc_end: i32, - tag: Tag, -} - -fn make_three(a: i64, b: i64, c: i64) Three { - ret Three { .a = a, .b = b, .c = c }; -} - -fn sum_three(t: Three) i64 { - ret t.a + t.b + t.c; -} - -fn make_token(s: i32, e: i32, t: Tag) Token { - ret Token { .loc_start = s, .loc_end = e, .tag = t }; -} - -fn test_ret_enum_struct() i32 { - var tok := make_token(10, 20, Tag.BlockComment); - if tok.loc_start != 10 { ret 1; } - if tok.loc_end != 20 { ret 2; } - if tok.tag != Tag.BlockComment { ret 3; } - ret 0; -} - -fn test_nested_ret_enum() i32 { - var tok := make_token(1, 5, Tag.Ident); - if tok.tag != Tag.Ident { ret 1; } - var tok2 := make_token(6, 9, Tag.Number); - if tok2.tag != Tag.Number { ret 2; } - if tok.tag != Tag.Ident { ret 3; } - ret 0; -} - -fn test_copy_token() i32 { - var tok := make_token(0, 100, Tag.LineComment); - var c := tok; - if c.loc_start != 0 { ret 1; } - if c.tag != Tag.LineComment { ret 2; } - c.tag = Tag.Ident; - if tok.tag != Tag.LineComment { ret 3; } - if c.tag != Tag.Ident { ret 4; } - ret 0; -} - -fn test_pass_token(t: Token) i32 { - if t.tag != Tag.Number { ret 1; } - if t.loc_start != 42 { ret 2; } - ret 0; -} - -fn test_param_pass_token() i32 { - var tok := make_token(42, 99, Tag.Number); - var r := test_pass_token(tok); - if r != 0 { ret r; } - ret 0; -} - -fn test_get_tag(tok: Token) Tag { - ret tok.tag; -} - -fn test_chain_func_call() i32 { - var tok := make_token(1, 2, Tag.BlockComment); - var tg := test_get_tag(tok); - if tg != Tag.BlockComment { ret 1; } - var tok2 := make_token(3, 4, Tag.LineComment); - var tg2 := test_get_tag(tok2); - if tg2 != Tag.LineComment { ret 2; } - ret 0; -} - -fn test_ret_multi_slot_struct() i32 { - var t := make_three(10, 20, 30); - if t.a != 10 { ret 1; } - if t.b != 20 { ret 2; } - if t.c != 30 { ret 3; } - ret 0; -} - -fn test_pass_struct_by_value() i32 { - var t := make_three(10, 20, 30); - var sum := sum_three(t); - if sum != 60 { ret 1; } - ret 0; -} - -fn test_copy_struct() i32 { - var t := make_three(10, 20, 30); - var t2: Three; - t2 = t; - if t2.a != 10 { ret 1; } - t2.a = 99; - if t.a != 10 { ret 2; } - if t2.a != 99 { ret 3; } - ret 0; -} - -fn test_multi_calls() i32 { - var ta := make_three(5, 10, 15); - var tb := make_three(20, 25, 30); - if ta.a + ta.b + ta.c != 30 { ret 1; } - if tb.a + tb.b + tb.c != 75 { ret 2; } - ret 0; -} - -fn test_literal_arg() i32 { - var sum := sum_three(Three { .a = 7, .b = 8, .c = 9 }); - if sum != 24 { ret 1; } - ret 0; -} - -fn main() i32 { - /* struct 字段访问 */ - var p: Pair; - p.a = 1; - p.b = 2; - if p.a != 1 { ret 1; } - if p.b != 2 { ret 2; } - - /* 同一类型复用 */ - var p2: Pair; - p2.a = 10; - p2.b = 20; - if p2.a + p2.b != 30 { ret 3; } - - /* 不影响其他实例 */ - if p.a != 1 { ret 4; } - - /* 内联 type 定义(在函数内) */ - type Triple = struct { - x: i32, - y: i32, - z: i32, - } - - var t: Triple; - t.x = 5; - t.y = 10; - t.z = 15; - if t.x + t.y + t.z != 30 { ret 5; } - - /* 结构体字段运算 */ - var calc: Pair; - calc.a = 7; - calc.b = 3; - var r := calc.a * calc.b + calc.a - calc.b; - if r != 25 { ret 6; } - - /* 结构体嵌套 */ - type Outer = struct { - inner: Inner, - extra: i32, - type Inner = struct { - val: i32, - } - } - - var o: Outer; - o.inner.val = 42; - o.extra = 58; - if o.inner.val != 42 { ret 7; } - if o.extra != 58 { ret 8; } - - /* 多 slot 结构体返回值测试 */ - var r9 := test_ret_multi_slot_struct(); - if r9 != 0 { ret 100; } - var r10 := test_pass_struct_by_value(); - if r10 != 0 { ret 101; } - var r11 := test_copy_struct(); - if r11 != 0 { ret 102; } - var r12 := test_multi_calls(); - if r12 != 0 { ret 103; } - var r13 := test_literal_arg(); - if r13 != 0 { ret 104; } - - /* 含 enum 字段的结构体返回值测试 */ - var r14 := test_ret_enum_struct(); - if r14 != 0 { ret 110; } - var r15 := test_nested_ret_enum(); - if r15 != 0 { ret 111; } - var r16 := test_copy_token(); - if r16 != 0 { ret 112; } - var r17 := test_param_pass_token(); - if r17 != 0 { ret 113; } - var r18 := test_chain_func_call(); - if r18 != 0 { ret 114; } - - ret 0; -} diff --git a/stage1/test11_enum.spl b/stage1/test11_enum.spl deleted file mode 100644 index d345596..0000000 --- a/stage1/test11_enum.spl +++ /dev/null @@ -1,29 +0,0 @@ -/* ===== 模块5:复合类型 ===== - * test11_enum — 枚举 - * 难度:3/5 - * 验证点:enum 定义、简单枚举值、带数据枚举变体 - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; - -type Color = enum { - Red, - Green, - Blue, -} - -type Expr = enum { - val: i32, - tag: Tag, - - type Tag = enum { - TagA, - TagB, - TagC, - } -} - -fn main() i32 { - vm_printf("enum values: %d %d %d\n", Color.Red, Color.Green, Color.Blue); - vm_printf("enum values: %d %d %d\n", Expr.Tag.TagA, Expr.Tag.TagB, Expr.Tag.TagC); - ret 0; -} diff --git a/stage1/test12_functions.spl b/stage1/test12_functions.spl deleted file mode 100644 index 83a7a61..0000000 --- a/stage1/test12_functions.spl +++ /dev/null @@ -1,55 +0,0 @@ -/* ===== 模块6:函数 ===== - * test12_functions — 函数调用 - * 难度:2/5 - * 验证点:函数定义与调用、参数传递、返回值、多个参数 - */ -fn add(a: i32, b: i32) i32 { - ret a + b; -} - -fn sub(a: i32, b: i32) i32 { - ret a - b; -} - -fn mul(a: i32, b: i32) i32 { - ret a * b; -} - -fn identity(x: i32) i32 { - ret x; -} - -fn addr(x: *i32) *i32 { - ret x; -} - -fn main() i32 { - /* 函数调用 */ - var r1 := add(3, 4); - if r1 != 7 { ret 1; } - - var r2 := sub(10, 3); - if r2 != 7 { ret 2; } - - var r3 := mul(6, 7); - if r3 != 42 { ret 3; } - - /* 函数嵌套调用 */ - var r4 := add(mul(2, 3), sub(10, 4)); - if r4 != 12 { ret 4; } - - /* 函数返回值的传递 */ - var r5 := identity(99); - if r5 != 99 { ret 5; } - - /* 多个参数 */ - var r6 := add(add(1, 2), add(3, 4)); - if r6 != 10 { ret 6; } - - /* 返回地址 */ - var r7 := addr(&r6); - if r7 != &r6 { ret 7; } - if r7.* != 10 { ret 8; } - - ret 0; -} diff --git a/stage1/test13_extern.spl b/stage1/test13_extern.spl deleted file mode 100644 index 3275b90..0000000 --- a/stage1/test13_extern.spl +++ /dev/null @@ -1,35 +0,0 @@ -/* ===== 模块6:函数 ===== - * test13_extern — 外部 VM 函数与字符串 - * 难度:2/5 - * 验证点:@extern(vm) 声明、vm_printf 调用、 - * 字符串字面量、字符串参数传递 - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; -@extern(vm) fn vm_strlen(s: *u8) i32; -@extern(vm) fn vm_strcmp(a: *u8, b: *u8) i32; - -fn main() i32 { - /* vm_printf 输出测试 */ - vm_printf("hello spl\n"); - vm_printf("%d %d %d\n", 1, 2, 3); - vm_printf("chars: %c%c\n", 'A', 'B'); - - /* 字符串字面量用于 extern */ - var len := vm_strlen("hello"); - if len != 5 { ret 1; } - - /* 字符串比较 */ - var cmp := vm_strcmp("abc", "abc"); - if cmp != 0 { ret 2; } - - var cmp2 := vm_strcmp("abc", "def"); - if cmp2 == 0 { ret 3; } - - /* 字符串作为格式化参数 */ - vm_printf("string test: %s %s\n", "foo", "bar"); - - /* vm_printf 返回 void(不关心返回值)*/ - vm_printf("all extern tests done\n"); - - ret 0; -} diff --git a/stage1/test14_assignment.spl b/stage1/test14_assignment.spl deleted file mode 100644 index 5d34ee4..0000000 --- a/stage1/test14_assignment.spl +++ /dev/null @@ -1,56 +0,0 @@ -/* ===== 模块7:高级特性 ===== - * test14_assignment — 复合赋值 - * 难度:2/5 - * 验证点:+= -= *= /= %= &= |= ^= <<= >>= - */ -fn main() i32 { - var x: i32 = 10; - - /* += */ - x += 5; - if x != 15 { ret 1; } - - /* -= */ - x -= 3; - if x != 12 { ret 2; } - - /* *= */ - x *= 2; - if x != 24 { ret 3; } - - /* /= */ - x /= 4; - if x != 6 { ret 4; } - - /* %= */ - var y: i32 = 17; - y %= 5; - if y != 2 { ret 5; } - - /* &= */ - var a: i32 = 0xFF; - a &= 0x0F; - if a != 0x0F { ret 6; } - - /* |= */ - var b: i32 = 0xF0; - b |= 0x0F; - if b != 0xFF { ret 7; } - - /* ^= */ - var c: i32 = 0xFF; - c ^= 0xF0; - if c != 0x0F { ret 8; } - - /* <<= */ - var d: i32 = 1; - d <<= 4; - if d != 16 { ret 9; } - - /* >>= */ - var e: i32 = 64; - e >>= 3; - if e != 8 { ret 10; } - - ret 0; -} diff --git a/stage1/test15_defer.spl b/stage1/test15_defer.spl deleted file mode 100644 index f60853e..0000000 --- a/stage1/test15_defer.spl +++ /dev/null @@ -1,45 +0,0 @@ -/* ===== 模块7:高级特性 ===== - * test15_defer — 延迟执行 - * 难度:3/5 - * 验证点:defer 语句、defer 块、多个 defer(逆序执行)、 - * 函数中 defer、块作用域 defer - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; - -fn with_cleanup() void { - defer vm_printf(" inner defer\n"); - vm_printf(" inside with_cleanup\n"); -} - -fn main() i32 { - vm_printf("--- defer test ---\n"); - - /* defer 语句 */ - defer vm_printf("defer1\n"); - vm_printf("after defer1\n"); - - /* defer 块 */ - defer { - vm_printf("defer block\n"); - } - vm_printf("after defer block\n"); - - /* 函数内 defer */ - with_cleanup(); - vm_printf("after with_cleanup\n"); - - /* 多个 defer 应逆序执行出作用域应该立刻执行,包括循环作用域 */ - { - defer vm_printf("block defer last\n"); - defer vm_printf("block defer middle\n"); - defer vm_printf("block defer first (should print third)\n"); - } - - /* 多个 defer 应逆序执行 */ - defer vm_printf("defer last\n"); - defer vm_printf("defer middle\n"); - defer vm_printf("defer first (should print third)\n"); - - vm_printf("--- defer test end ---\n"); - ret 0; -} diff --git a/stage1/test16_methods.spl b/stage1/test16_methods.spl deleted file mode 100644 index 47e9fe6..0000000 --- a/stage1/test16_methods.spl +++ /dev/null @@ -1,48 +0,0 @@ -/* ===== 模块7:高级特性 ===== - * test16_methods — 类型关联方法 - * 难度:3/5 - * 验证点:struct 方法、enum 方法、self 参数自动填充、方法调用 - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; - -type Point = struct { - x: i32, - y: i32, - - fn init(x: i32, y: i32) Point { - ret Point { .x = x, .y = y }; - } - - fn dump(self: *Point) void { - vm_printf("Point(%d, %d)\n", self.x, self.y); - } -} - -type Expr = enum { - Int: i32, - Add: struct { left: *Expr, right: *Expr }, - - fn eval(self: *Expr) i32 { - match self { - .Int[val] => { ret val; }, - .Add[sub] => { ret eval(sub.left) + eval(sub.right); } - } - ret 0; - } -} - -fn main() i32 { - /* struct 方法调用 */ - var p: Point = Point.init(3, 4); - p.dump(&p); - - /* enum 方法 + match */ - var expr_l := Expr { .Int = 3 }; - var expr_r := Expr { .Int = 4 }; - var expr := Expr { .Add = .{ .left = expr_l, .right = expr_r } }; - var result := expr.eval(&expr); - vm_printf("eval result: %d\n", result); - if result != 7 { ret 1; } - - ret 0; -} diff --git a/stage1/test17_integration.spl b/stage1/test17_integration.spl deleted file mode 100644 index d8995a7..0000000 --- a/stage1/test17_integration.spl +++ /dev/null @@ -1,95 +0,0 @@ -/* ===== 模块8:综合 ===== - * test17_integration — 综合测试 - * 难度:3/5 - * 验证点:多特性组合——指针 + 结构体 + 函数 + 循环 + 数组 + 切片 - */ -@extern(vm) fn vm_printf(fmt: *u8, ...) void; - -type Point = struct { - x: i32, - y: i32, -} - -/* 计算点积 */ -fn dot(a: *Point, b: *Point) i32 { - ret a.x * b.x + a.y * b.y; -} - -/* 递归斐波那契 */ -fn fib(n: i32) i32 { - if n <= 1 { ret n; } - ret fib(n - 1) + fib(n - 2); -} - -fn main() i32 { - /* 综合:指针 + 结构体 + 函数 */ - var p1: Point; - p1.x = 3; - p1.y = 4; - - var p2: Point; - p2.x = 5; - p2.y = 6; - - var d := dot(&p1, &p2); - /* 3*5 + 4*6 = 15 + 24 = 39 */ - if d != 39 { ret 1; } - - /* 综合:数组 + while 循环 */ - var arr: [5]i32 = [5]i32{1, 2, 3, 4, 5}; - var sum: i32 = 0; - var i: i32 = 0; - while i < 5 { - sum = sum + arr[i]; - i = i + 1; - } - if sum != 15 { ret 2; } - - /* 综合:切片 + for */ - var sl: []i32 = arr[1..4]; - var sl_sum: i32 = 0; - for sl as val { - sl_sum = sl_sum + val; - } - if sl_sum != 9 { ret 3; } /* 2+3+4 */ - - /* 综合:递归 */ - var f := fib(10); - if f != 55 { ret 4; } - - /* 综合:loop/break/continue */ - var n: i32 = 0; - var count: i32 = 0; - loop { - n = n + 1; - if n == 2 { continue; } - count = count + 1; - if n >= 5 { break; } - } - /* 执行 n=1,3,4,5 共 4 次 (n=2 被 continue) */ - if count != 4 { ret 5; } - - /* 综合:指针修改结构体 */ - var pp: *Point = &p1; - pp.x = 10; - pp.y = 20; - if p1.x != 10 { ret 6; } - if p1.y != 20 { ret 7; } - - /* 综合:嵌套控制流 */ - var mat: [3]i32 = [3]i32{1, 2, 3}; - var outer_sum: i32 = 0; - var j: i32 = 0; - while j < 3 { - var k: i32 = 0; - while k < 3 { - if mat[j] > mat[k] { - outer_sum = outer_sum + 1; - } - k = k + 1; - } - j = j + 1; - } - if outer_sum != 3 { ret 8; } - ret 0; -} diff --git a/stage1/test18_match.spl b/stage1/test18_match.spl deleted file mode 100644 index f7b977d..0000000 --- a/stage1/test18_match.spl +++ /dev/null @@ -1,488 +0,0 @@ -/* ===== 模块4:match 语句 ===== - * test18_match — match 枚举匹配 + 整数匹配(类似 switch) - * 难度:3/5 - * 验证点:枚举匹配、带数据绑定、结构体字段绑定、枚举指针、 - * 整数自变量匹配、默认分支 _ - */ - -/* ---- 简单枚举(无数据) ---- */ -type Color = enum { - Red; - Green; - Blue; -} - -/* ---- 带 i32 数据的枚举 ---- */ -type Optional = enum { - Some: i32; - None; -} - -/* ---- 带结构体数据的枚举 ---- */ -type Point = struct { - x: i32; - y: i32; -} - -type Shape = enum { - Circle: i32; - Rect: Point; -} - -/* ---- 多变体枚举 ---- */ -type ActionResult = enum { - Success: i32; - NotFound; - Timeout: i32; - Error: *u8; -} - -/* ============================================================ - * 测试 1: 无数据枚举匹配 - * ============================================================ */ - -fn test_color_match() i32 { - var c: Color = Color { .Red }; - var val: i32 = 0; - - match c { - .Red => { val = 1; }, - .Green => { val = 2; }, - .Blue => { val = 3; } - } - if val != 1 { ret 1; } - - c = Color { .Green }; - match c { - .Red => { val = 0; }, - .Green => { val = 2; }, - .Blue => { val = 0; } - } - if val != 2 { ret 2; } - - c = Color { .Blue }; - match c { - .Red => { val = 0; }, - .Green => { val = 0; }, - .Blue => { val = 3; } - } - if val != 3 { ret 3; } - - ret 0; -} - -/* ============================================================ - * 测试 2: 带 i32 数据枚举匹配 - * ============================================================ */ - -fn test_optional_match() i32 { - var o: Optional = Optional { .Some = 42 }; - - match o { - .Some[val] => { - if val != 42 { ret 1; } - }, - .None => { - ret 2; - } - } - - o = Optional { .None }; - var is_none: i32 = 0; - match o { - .Some[val] => {}, - .None => { is_none = 1; } - } - if is_none != 1 { ret 3; } - - /* 多次提取不同值 */ - o = Optional { .Some = 99 }; - match o { - .Some[val] => { - if val != 99 { ret 4; } - }, - .None => { ret 5; } - } - - ret 0; -} - -/* ============================================================ - * 测试 3: 带结构体数据枚举匹配(多字段绑定) - * ============================================================ */ - -fn test_shape_match() i32 { - /* Circle: 单数据 */ - var s: Shape = Shape { .Circle = 10 }; - match s { - .Circle[r] => { - if r != 10 { ret 1; } - }, - .Rect[p] => { - ret 2; - } - } - - /* Rect: 结构体数据,绑定为 (x, y) 对应 Point 的字段 */ - s = Shape { .Rect = Point { .x = 3, .y = 4 } }; - match s { - .Circle[r] => { ret 3; }, - .Rect[p] => { - if p.x != 3 { ret 4; } - if p.y != 4 { ret 5; } - } - } - - ret 0; -} - -/* ============================================================ - * 测试 4: 多数据变体枚举匹配 - * ============================================================ */ - -fn test_action_result_match() i32 { - var r: ActionResult = ActionResult { .Success = 200 }; - match r { - .Success[code] => { - if code != 200 { ret 1; } - }, - .NotFound => { - ret 2; - }, - .Timeout[ms] => { - ret 3; - }, - .Error[msg] => { - ret 4; - } - } - - r = ActionResult { .NotFound }; - var found: i32 = 1; - match r { - .Success[code] => { found = 0; }, - .NotFound => { }, - .Timeout[ms] => { found = 0; }, - .Error[msg] => { found = 0; } - } - if found != 1 { ret 5; } - - r = ActionResult { .Timeout = 5000 }; - match r { - .Success[code] => { ret 6; }, - .NotFound => { ret 7; }, - .Timeout[ms] => { - if ms != 5000 { ret 8; } - }, - .Error[msg] => { ret 9; } - } - - ret 0; -} - -/* ============================================================ - * 测试 5: 枚举指针匹配 - * ============================================================ */ - -fn test_ptr_match() i32 { - var c: Color = Color { .Green }; - var p: *Color = &c; - - match p { - .Red => { ret 1; }, - .Green => { }, - .Blue => { ret 2; } - } - - /* 修改后通过指针匹配 */ - c = Color { .Blue }; - match p { - .Red => { ret 3; }, - .Green => { ret 4; }, - .Blue => { } - } - - ret 0; -} - -/* ============================================================ - * 测试 6: match 作为函数返回值 - * ============================================================ */ - -fn classify_color(c: Color) i32 { - match c { - .Red => { ret 1; }, - .Green => { ret 2; }, - .Blue => { ret 3; } - } - ret 0; -} - -fn test_match_in_func() i32 { - var r: i32; - - r = classify_color(Color { .Red }); - if r != 1 { ret 1; } - - r = classify_color(Color { .Green }); - if r != 2 { ret 2; } - - r = classify_color(Color { .Blue }); - if r != 3 { ret 3; } - - ret 0; -} - -/* ============================================================ - * 测试 7: match 嵌套在循环中 - * ============================================================ */ - -fn test_match_in_loop() i32 { - var i: i32 = 0; - var sum: i32 = 0; - - while i < 3 { - var o: Optional; - if i == 0 { - o = Optional { .Some = 10 }; - } else if i == 1 { - o = Optional { .Some = 20 }; - } else { - o = Optional { .Some = 30 }; - } - - match o { - .Some[val] => { - sum = sum + val; - }, - .None => { } - } - i = i + 1; - } - if sum != 60 { ret 1; } - - ret 0; -} - -/* ============================================================ - * 测试 8: 整数 match(类似 switch) - * ============================================================ */ - -fn test_int_match() i32 { - var x: i32 = 2; - var result: i32 = 0; - - match x { - 1 => { result = 10; }, - 2 => { result = 20; }, - 3 => { result = 30; } - } - if result != 20 { ret 1; } - - /* 匹配第一个值 */ - x = 1; - match x { - 1 => { result = 100; }, - 2 => { result = 200; }, - 3 => { result = 300; } - } - if result != 100 { ret 2; } - - /* 匹配最后一个值 */ - x = 3; - match x { - 1 => { result = 1000; }, - 2 => { result = 2000; }, - 3 => { result = 3000; } - } - if result != 3000 { ret 3; } - - ret 0; -} - -/* ============================================================ - * 测试 9: 整数 match 带默认分支 _ - * ============================================================ */ - -fn test_int_match_default() i32 { - var x: i32 = 99; - var result: i32 = 0; - - match x { - 1 => { result = 1; }, - 2 => { result = 2; }, - _ => { result = 99; } - } - if result != 99 { ret 1; } - - /* 默认分支未触发 */ - x = 1; - match x { - 1 => { result = 1; }, - 2 => { result = 2; }, - _ => { result = 99; } - } - if result != 1 { ret 2; } - - ret 0; -} - -/* ============================================================ - * 测试 10: 整数 match 多个值跳转到相同逻辑 - * ============================================================ */ - -fn test_int_match_multi() i32 { - var x: i32 = 2; - var result: i32 = 0; - - /* 每个分支独立 */ - match x { - 0 => { result = 0; }, - 1 => { result = 1; }, - 2 => { result = 2; }, - 3 => { result = 3; } - } - if result != 2 { ret 1; } - - /* 负数和零 */ - x = -1; - match x { - -1 => { result = -1; }, - 0 => { result = 0; }, - 1 => { result = 1; } - } - if result != -1 { ret 2; } - - x = 0; - match x { - -1 => { result = -1; }, - 0 => { result = 0; }, - 1 => { result = 1; } - } - if result != 0 { ret 3; } - - ret 0; -} - -/* ============================================================ - * 测试 11a: match 多值 fallthrough: 1, 2, 3 => body - * ============================================================ */ - -fn test_int_match_fallthrough() i32 { - var x: i32; - var r: i32; - - /* 三个值映射到同一个 body */ - x = 1; r = 0; - match x { - 1, 2, 3 => { r = 10; }, - 4, 5 => { r = 20; } - } - if r != 10 { ret 1; } - - x = 3; - match x { - 1, 2, 3 => { r = 10; }, - 4, 5 => { r = 20; } - } - if r != 10 { ret 2; } - - x = 5; - match x { - 1, 2, 3 => { r = 10; }, - 4, 5 => { r = 20; } - } - if r != 20 { ret 3; } - - /* 单一值(非fallthrough)仍然正常 */ - x = 7; r = 0; - match x { - 1 => { r = 1; }, - 7 => { r = 7; } - } - if r != 7 { ret 4; } - - /* 多个负数值 */ - x = -2; r = 0; - match x { - -3, -2, -1 => { r = 100; }, - 0, 1 => { r = 200; } - } - if r != 100 { ret 5; } - - ret 0; -} - -/* ============================================================ - * 测试 11b: match with body 中修改变量 - * ============================================================ */ - -fn test_match_with_side_effects() i32 { - var x: i32 = 3; - var acc: i32 = 0; - - match x { - 1 => { acc = acc + 1; }, - 2 => { acc = acc + 2; }, - 3 => { acc = acc + 3; }, - 4 => { acc = acc + 4; } - } - if acc != 3 { ret 1; } - - /* 再次 match 同一个变量 */ - match x { - 1 => { acc = acc + 1; }, - 2 => { acc = acc + 2; }, - 3 => { acc = acc + 3; }, - 4 => { acc = acc + 4; } - } - if acc != 6 { ret 2; } - - ret 0; -} - -/* ============================================================ - * 主函数 - * ============================================================ */ - -fn main() i32 { - var r: i32; - - r = test_color_match(); - if r != 0 { ret r; } - - r = test_optional_match(); - if r != 0 { ret r + 10; } - - r = test_shape_match(); - if r != 0 { ret r + 20; } - - r = test_action_result_match(); - if r != 0 { ret r + 30; } - - r = test_ptr_match(); - if r != 0 { ret r + 40; } - - r = test_match_in_func(); - if r != 0 { ret r + 50; } - - r = test_match_in_loop(); - if r != 0 { ret r + 60; } - - r = test_int_match(); - if r != 0 { ret r + 70; } - - r = test_int_match_default(); - if r != 0 { ret r + 80; } - - r = test_int_match_multi(); - if r != 0 { ret r + 90; } - - r = test_match_with_side_effects(); - if r != 0 { ret r + 100; } - - r = test_int_match_fallthrough(); - if r != 0 { ret r + 110; } - - ret 0; -} diff --git a/stage1/test19_hardarray.spl b/stage1/test19_hardarray.spl deleted file mode 100644 index bc5505c..0000000 --- a/stage1/test19_hardarray.spl +++ /dev/null @@ -1,184 +0,0 @@ -/* ===== 进阶数组与切片 ===== - * 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; -} diff --git a/stage1/test20_complex.spl b/stage1/test20_complex.spl deleted file mode 100644 index 8e60693..0000000 --- a/stage1/test20_complex.spl +++ /dev/null @@ -1,320 +0,0 @@ -/* ===== 复杂类型嵌套综合测试 ===== - * test20_complex ?结构体嵌套、切片、数组、方法、类型别名、枚举等 - * 难度?/5 - */ -/* ---- 基础结构?---- */ -type Point = struct { - x: i32, - y: i32, -} - -/* ---- 嵌套结构?---- */ -type Rect = struct { - min: Point, - max: Point, -} - -/* ---- 含切片字段的结构?(核心 bug 测试) ---- */ -type Buffer = struct { - data: []u8, - len: usize, -} - -/* ---- 含数组字段的结构?---- */ -type MatrixRow = struct { - items: [4]i32, -} - -/* ---- 含指针字段的结构?---- */ -type Node = struct { - ptr: *i32, - val: i32, -} - -/* ---- 多层级嵌套:结构体里的结构体里的切片 ---- */ -type Bundle = struct { - name: *u8, - buf: Buffer, - row: MatrixRow, - pt: Point, -} - -/* ---- 枚举含数?---- */ -type Status = enum { - Active: i32; - Inactive; - Pending: Point; -} - -/* ---- 含方法的结构?(方法定义在结构体内部) ---- */ -type Counter = struct { - val: i32, - - fn inc(self: *Counter) i32 { - self.val = self.val + 1; - ret self.val; - } - - fn add(self: *Counter, n: i32) i32 { - self.val = self.val + n; - ret self.val; - } - - fn reset(self: *Counter) { - self.val = 0; - } - - fn get(self: *Counter) i32 { - ret self.val; - } -} - -/* ============================================================ - * 测试 1: 切片在结构体内部初始?(修复的核?bug) - * ============================================================ */ - -fn test_slice_in_struct() i32 { - var raw: [4]u8; - raw[0] = 65; raw[1] = 66; raw[2] = 67; raw[3] = 68; - - /* Bug fix: { .ptr = ..., .len = ... } inside struct literal */ - var b: Buffer = Buffer { .data = .{ .ptr = &raw[0], .len = 4 }, .len = 4 }; - - if b.len != 4 { ret 1; } - if b.data[0] != 65 { ret 2; } - if b.data[1] != 66 { ret 3; } - if b.data[3] != 68 { ret 4; } - - /* Modify through slice ?verify reflection */ - b.data[0] = 90; - if raw[0] != 90 { ret 5; } - - /* Initialize with shorter slice */ - var b2: Buffer = Buffer { .data = .{ .ptr = &raw[2], .len = 2 }, .len = 2 }; - if b2.len != 2 { ret 6; } - if b2.data[0] != 67 { ret 7; } - - /* Slice field assignment via field access */ - b2.data.ptr = &raw[0]; - b2.data.len = 4; - if b2.data[0] != 90 { ret 8; } - if b2.data.len != 4 { ret 9; } - - ret 0; -} - -/* ============================================================ - * 测试 2: 结构体含数组字段 - * ============================================================ */ - -fn test_struct_with_array() i32 { - var mr: MatrixRow = MatrixRow { .items = [4]i32{10, 20, 30, 40} }; - - if mr.items[0] != 10 { ret 1; } - if mr.items[1] != 20 { ret 2; } - if mr.items[2] != 30 { ret 3; } - if mr.items[3] != 40 { ret 4; } - - /* 修改数组元素 */ - mr.items[2] = 99; - if mr.items[2] != 99 { ret 5; } - - ret 0; -} - -/* ============================================================ - * 测试 3: 嵌套结构体初始化 - * ============================================================ */ - -fn test_nested_struct() i32 { - var p: Point = Point { .x = 5, .y = 10 }; - if p.x != 5 { ret 1; } - if p.y != 10 { ret 2; } - - /* 嵌套结构体字面量 */ - var r: Rect = Rect { - .min = Point { .x = 1, .y = 2 }, - .max = Point { .x = 3, .y = 4 } - }; - if r.min.x != 1 { ret 3; } - if r.min.y != 2 { ret 4; } - if r.max.x != 3 { ret 5; } - if r.max.y != 4 { ret 6; } - - /* 修改嵌套字段 */ - r.min.x = 100; - if r.min.x != 100 { ret 7; } - if r.min.y != 2 { ret 8; } /* unchanged */ - - ret 0; -} - -/* ============================================================ - * 测试 4: 结构体成员方?(实例方法调用) - * ============================================================ */ - -fn test_struct_method() i32 { - var c: Counter = Counter { .val = 0 }; - - /* 实例方法调用 c.inc(&c) */ - var r1: i32 = c.inc(&c); - if r1 != 1 { ret 1; } - if c.val != 1 { ret 2; } - - /* 带参数方法调?c.add(&c, n) */ - var r2: i32 = c.add(&c, 5); - if r2 != 6 { ret 3; } - if c.val != 6 { ret 4; } - - /* 连续调用 (显式 self) */ - c.reset(&c); - if c.val != 0 { ret 5; } - - c.add(&c, 10); - c.inc(&c); - var r3: i32 = c.get(&c); - if r3 != 11 { ret 6; } - - ret 0; -} - -/* ============================================================ - * 测试 5: 结构体含指针字段 - * ============================================================ */ - -fn test_ptr_in_struct() i32 { - var v: i32 = 42; - var n: Node = Node { .ptr = &v, .val = 99 }; - - if n.val != 99 { ret 1; } - if n.ptr[0] != 42 { ret 2; } - - /* 通过指针修改 */ - v = 100; - if n.ptr[0] != 100 { ret 3; } - - /* 通过指针在结构体内修?*/ - n.ptr[0] = 200; - if v != 200 { ret 4; } - - ret 0; -} - -/* ============================================================ - * 测试 6: 多层级复杂嵌? - * ============================================================ */ - -fn test_complex_nesting() i32 { - var str_data: [5]u8; - str_data[0] = 72; str_data[1] = 101; - str_data[2] = 108; str_data[3] = 108; str_data[4] = 111; - - var bundle: Bundle = Bundle { - .name = &str_data[0], - .buf = Buffer { .data = .{ .ptr = &str_data[1], .len = 3 }, .len = 3 }, - .row = MatrixRow { .items = [4]i32{1, 2, 3, 4} }, - .pt = Point { .x = -5, .y = 15 } - }; - - /* Verify name */ - if bundle.name[0] != 72 { ret 1; } - if bundle.name[4] != 111 { ret 2; } - - /* Verify nested slice */ - if bundle.buf.len != 3 { ret 3; } - if bundle.buf.data[0] != 101 { ret 4; } - if bundle.buf.data[2] != 108 { ret 5; } - - /* Verify array field */ - if bundle.row.items[0] != 1 { ret 6; } - if bundle.row.items[3] != 4 { ret 7; } - - /* Verify nested struct field */ - if bundle.pt.x != -5 { ret 8; } - if bundle.pt.y != 15 { ret 9; } - - /* Modify nested slice */ - bundle.buf.data[1] = 87; /* 'W' */ - if str_data[2] != 87 { ret 10; } - - /* Modify nested array */ - bundle.row.items[2] = 33; - if bundle.row.items[2] != 33 { ret 11; } - - ret 0; -} - -/* ============================================================ - * 测试 7: 枚举含结构体数据 - * ============================================================ */ - -fn test_enum_complex() i32 { - var s: Status = Status { .Active = 42 }; - - /* Verify active variant */ - match s { - .Active[val] => { - if val != 42 { ret 1; } - }, - .Inactive => { - ret 2; - }, - .Pending[p] => { - ret 3; - } - } - - /* Test Inactive variant */ - var s2: Status = Status { .Inactive }; - var is_inactive: i32 = 0; - match s2 { - .Active[val] => {}, - .Inactive => { is_inactive = 1; }, - .Pending[p] => {} - } - if is_inactive != 1 { ret 4; } - - /* Test Pending variant with struct data */ - var s3: Status = Status { .Pending = Point { .x = 7, .y = 8 } }; - match s3 { - .Active[val] => { ret 5; }, - .Inactive => { ret 6; }, - .Pending[p] => { - if p.x != 7 { ret 7; } - if p.y != 8 { ret 8; } - } - } - - ret 0; -} - -/* ============================================================ - * 主函? - * ============================================================ */ - -fn main() i32 { - var r: i32; - - r = test_slice_in_struct(); - if r != 0 { ret r; } - - r = test_struct_with_array(); - if r != 0 { ret r + 100; } - - r = test_nested_struct(); - if r != 0 { ret r + 200; } - - r = test_struct_method(); - if r != 0 { ret r + 300; } - - r = test_ptr_in_struct(); - if r != 0 { ret r + 400; } - - r = test_complex_nesting(); - if r != 0 { ret r + 500; } - - r = test_enum_complex(); - if r != 0 { ret r + 600; } - - ret 0; -}