stage2 提供近乎完整的功能但出现严重性能问题 添加stage0的原生性能记录 stage1添加更多内置函数 nob重构代码使其更加健壮
This commit is contained in:
1 parent
b5a7a811b3
commit
e02b0c633a
35 files changed
+14018
-216
No files matched your search
@@ -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();
|
||||
}
|
||||
Reference in new issue
Block a user