// Expect retcode = 0 // comptime/const 求值的接口 seam:sema 只在此调用,未实现时返回 NotConst(放弃折叠、 // 不报错)。编译期生成的声明经 DeclSink 登记,不改 sema 表。 type .{ .Error } = @import("utils/error.spl"); type .{ .Vec } = @import("utils/vec.spl"); type Ast = @import("./ast.spl"); type Diag = @import("./diag.spl"); // 编译期值(当前仅标量)。 type EvalValue = enum { Int: usize, 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 = 完全不求值 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; } 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 块;当前不实现,直接 NotConst。 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(); }