131 lines
3.2 KiB
Plaintext
131 lines
3.2 KiB
Plaintext
// 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();
|
|
}
|