// Expect retcode = 0 // comptime / const 求值的**接口 seam**(本轮只占位,不实现求值)。 // // 目标:把「编译期求值」从 sema 主体里隔离出来,将来接一个解释器(可直接复用 // VM 或 AST 求值器)时不动 sema 结构。sema 只在 comptime 语句 / const 初始化 / // @import 等点调用这里;未实现时统一返回 NotConst(= 放弃折叠,不报错)。 // // 分块编译相关:eval 未来的产物是「编译期生成的声明」,统一经 DeclSink 登记, // 由驱动在固定点循环里插入并触发重跑;eval 自己不直接改 sema 表,避免重入。 type .{ .Error } = @import("utils/error.spl"); type .{ .Vec } = @import("utils/vec.spl"); type Ast = @import("./ast.spl"); type Diag = @import("./diag.spl"); // 编译期值:占位。未来扩展为 BigInt / 聚合 / 类型句柄等。 type EvalValue = enum { Int: usize, // TODO: BigInt Bool: bool, } type EvalOutcome = enum { Value: EvalValue, NotConst, // 不是编译期常量(正常放弃,不产生诊断) Err: Error, // 求值出错(诊断由 eval 侧发出) } // comptime 生成声明的出口:eval 只登记,插入/重跑由驱动负责。 type DeclSink = struct { items: Vec, // usize:待插入的 AST 节点引用 } type DeclSinkResult = enum { Ok: DeclSink, Err: Error, } // 求值上下文(借用 sink 与 diag;本轮不持有所有权)。 type Eval = @self; sink: *DeclSink, // 借用,可为 null diag: *Diag, // 借用,可为 null enabled: bool, // false = 完全不求值(等价旧行为) // ---- DeclSink ---- fn sink_new(): DeclSinkResult { var s = DeclSink { .items = Vec.blank(@sizeof(usize), @alignof(usize)) }; ret .Ok(s); } fn sink_drop(self: *DeclSink) { Vec.drop(&self.items); } fn sink_push(self: *DeclSink, node_ref: usize): bool { match Vec.push(&self.items, &node_ref as *u8) { .Ok => { ret true; }, .Err(error) => { ret false; }, } ret false; } fn sink_len(self: *DeclSink): usize { ret self.items.len; } // ---- Eval ---- fn new(sink: *DeclSink, diag: *Diag, enabled: bool): Eval { ret Eval { .sink = sink, .diag = diag, .enabled = enabled, }; } fn is_enabled(self: *Eval): bool { ret self.enabled; } // 求值一个表达式。本轮一律 NotConst(可由调用方作为「放弃折叠」处理)。 fn eval_expr(self: *Eval, ast: *Ast, ref: usize): EvalOutcome { if !self.enabled { ret .NotConst; } ret .NotConst; } // 执行一个 comptime 块(可能产生声明,登记到 sink)。本轮不做。 fn run_block(self: *Eval, ast: *Ast, ref: usize): EvalOutcome { if !self.enabled { ret .NotConst; } ret .NotConst; } // 顶层 const 初始化求值。本轮不做。 fn eval_const_init(self: *Eval, ast: *Ast, ref: usize): EvalOutcome { if !self.enabled { ret .NotConst; } ret .NotConst; } // ---- 测试 ---- fn test_sink() { var sink: DeclSink = undefined; match sink_new() { .Ok(v) => { sink = v; }, .Err(error) => { @assert(false, "sink new failed"); }, } defer { sink_drop(&sink); } @assert(sink_len(&sink) == 0, "empty sink"); @assert(sink_push(&sink, 42), "push"); @assert(sink_len(&sink) == 1, "one item"); } fn test_stub_outcome() { var sink: DeclSink = undefined; match sink_new() { .Ok(v) => { sink = v; }, .Err(error) => { @assert(false, "sink new failed"); }, } defer { sink_drop(&sink); } var ev = new(&sink, null, true); @assert(is_enabled(&ev), "enabled"); var out = eval_expr(&ev, null, 0); match out { .NotConst => {}, _ => { @assert(false, "stub returns NotConst"); }, } var ev2 = new(null, null, false); @assert(!is_enabled(&ev2), "disabled"); } fn main() { test_sink(); test_stub_outcome(); }