stage2 提供近乎完整的功能但出现严重性能问题 添加stage0的原生性能记录 stage1添加更多内置函数 nob重构代码使其更加健壮

This commit is contained in:
zzy committed 2026-09-19 18:08:43 +08:00
1 parent b5a7a811b3
commit e02b0c633a
35 files changed
+14018 -216

No files matched your search

+224
View File
@@ -0,0 +1,224 @@
// Expect retcode = 0
// 作用域树(移植自 stage1/spl_scope.c)。每个作用域是一张名字 -> Symbol 表,
// 节点用 parent 指向父作用域;查找从 current_scope 沿父链上溯(支持遮蔽)。
// 名字是 ByteView(借用源/AST);Map 复制键值字节,但 ByteView 指向的字节由
// 调用方保证存活。node 字段是 def.spl 的 DefId。
type .{ .Error } = @import("utils/error.spl");
type .{ .Vec } = @import("utils/vec.spl");
type .{ .Map } = @import("utils/map.spl");
type .{ .ByteView } = @import("utils/byte_view.spl");
type .{ .hash_view, .eq_view } = @import("utils/hash.spl");
type SymbolKind = enum {
Error,
Var,
Member,
Fn,
Type,
}
type Symbol = struct {
name: ByteView,
kind: SymbolKind,
node: usize, // DefId
}
type ScopeNode = struct {
parent: usize,
symbols: Map,
}
type Scope = @self;
scopes: Vec, // ScopeNode
root_scope: usize,
current_scope: usize,
type ScopeResult = enum {
Ok: Scope,
Err: Error,
}
fn new_map(): Map {
ret Map.new(@sizeof(ByteView), @alignof(ByteView), @sizeof(Symbol), @alignof(Symbol),
hash_view, eq_view);
}
fn new(): ScopeResult {
var sc = Scope {
.scopes = Vec.blank(@sizeof(ScopeNode), @alignof(ScopeNode)),
.root_scope = 0,
.current_scope = 0,
};
var sentinel = ScopeNode { .parent = 0, .symbols = new_map() };
match Vec.push(&sc.scopes, &sentinel as *u8) {
.Ok => {},
.Err(error) => {
Vec.drop(&sc.scopes);
Map.drop(&sentinel.symbols);
ret .Err(error);
},
}
ret .Ok(sc);
}
fn drop(self: *Scope) {
var i: usize = 0;
while i < self.scopes.len {
var n = node(self, i);
if n != null {
Map.drop(&n.symbols);
}
i = i + 1;
}
Vec.drop(&self.scopes);
self.root_scope = 0;
self.current_scope = 0;
}
// id 0 与越界返回 null。
fn node(self: *Scope, id: usize): *ScopeNode {
if id == 0 || id >= self.scopes.len { ret null; }
match Vec.get(&self.scopes, id) {
.Ok(ptr) => { ret ptr as *ScopeNode; },
.Err(error) => { ret null; },
}
ret null;
}
// 新作用域 parent = 当前作用域;不自动切换 current(调用方负责,见 sema)。
fn alloc(self: *Scope): usize {
var n = ScopeNode { .parent = self.current_scope, .symbols = new_map() };
match Vec.push(&self.scopes, &n as *u8) {
.Ok => {},
.Err(error) => {
Map.drop(&n.symbols);
ret 0;
},
}
ret self.scopes.len - 1;
}
// 插入符号;同名已存在返回 false(不改动)。
fn insert(self: *Scope, id: usize, symbol: Symbol): bool {
if id == 0 || id >= self.scopes.len { ret false; }
var n = node(self, id);
if n == null { ret false; }
var old = Symbol {
.name = ByteView.empty(),
.kind = .Error,
.node = 0,
};
match Map.get(&n.symbols, &symbol.name as *u8, &old as *u8) {
.Found => { ret false; },
.NotFound => {},
}
match Map.put(&n.symbols, &symbol.name as *u8, &symbol as *u8) {
.Ok => { ret true; },
.Err(error) => { ret false; },
}
ret false;
}
// 从 current_scope 沿父链查找;找到填 out 返回 true。
fn find(self: *Scope, name: ByteView, out: *Symbol): bool {
if out == null { ret false; }
var id = self.current_scope;
while id != 0 {
var n = node(self, id);
if n == null { ret false; }
match Map.get(&n.symbols, &name as *u8, out as *u8) {
.Found => { ret true; },
.NotFound => {},
}
id = n.parent;
}
ret false;
}
// ---- 测试 ----
fn sym(name: []u8, kind: SymbolKind, node: usize): Symbol {
ret Symbol {
.name = ByteView.from_slice(name),
.kind = kind,
.node = node,
};
}
fn test_alloc_and_find() {
var sc: Scope = undefined;
match new() {
.Ok(v) => { sc = v; },
.Err(error) => { @assert(false, "scope new failed"); },
}
defer { drop(&sc); }
@assert(sc.root_scope == 0 && sc.current_scope == 0, "initial");
// root
var root = alloc(&sc);
sc.root_scope = root;
sc.current_scope = root;
// module scope(child of root)
var mod = alloc(&sc);
sc.current_scope = mod;
@assert(insert(&sc, mod, sym("x", .Var, 11)), "insert x");
@assert(!insert(&sc, mod, sym("x", .Var, 12)), "duplicate x");
// 函数作用域
var fn_scope = alloc(&sc);
sc.current_scope = fn_scope;
var out = sym("", .Error, 0);
@assert(find(&sc, ByteView.from_slice("x"), &out), "find x from child");
@assert(out.node == 11, "x def id");
// 遮蔽:函数内层再定义 x
@assert(insert(&sc, fn_scope, sym("x", .Fn, 99)), "shadow x");
@assert(find(&sc, ByteView.from_slice("x"), &out), "find shadow");
@assert(out.node == 99, "shadow def id");
// 未定义
@assert(!find(&sc, ByteView.from_slice("nope"), &out), "missing");
// 父链结构
var m = node(&sc, mod);
var f = node(&sc, fn_scope);
@assert(m != null && m.parent == root, "mod parent");
@assert(f != null && f.parent == mod, "fn parent");
}
fn test_kinds_isolated() {
var sc: Scope = undefined;
match new() {
.Ok(v) => { sc = v; },
.Err(error) => { @assert(false, "scope new failed"); },
}
defer { drop(&sc); }
var a = alloc(&sc);
sc.current_scope = a;
@assert(insert(&sc, a, sym("T", .Type, 1)), "type T");
@assert(insert(&sc, a, sym("f", .Fn, 2)), "fn f");
var out = sym("", .Error, 0);
@assert(find(&sc, ByteView.from_slice("T"), &out), "find T");
var kind_matches = false;
match out.kind {
.Type => { kind_matches = true; },
_ => {},
}
@assert(kind_matches, "T kind");
@assert(find(&sc, ByteView.from_slice("f"), &out), "find f");
@assert(out.node == 2, "f def id");
}
fn main() {
test_alloc_and_find();
test_kinds_isolated();
}