Files
doslang-mirror/fec/tests/exec/interns.fe
T
coolguy b0cc737c6b GOAL P3-5: StrId 를 키로 -- 별도 IntMap 은 필요 없다
std.map 은 바이트 열을 키로 받는다. 이름의 번호를 네 바이트로 써 내려놓으면
그대로 심볼 표가 된다. 감사가 권한 IntMap(V) 를 따로 만들 이유가 없고, 그
쪽이 trait 없는 v0.1 과도 덜 싸운다.

intern.key_of 가 그 네 바이트를 써준다. 리졸버가 스코프마다 할 일이라
손으로 풀게 두지 않았다.

  scope x 10 y 20 of 2

245/245, 38/38.
2026-08-17 16:28:47 +09:00

74 lines
2.5 KiB
Plaintext

// EXIT:0
// OUTPUT:ids 0 1 2 count 3
// OUTPUT:again 0 same yes count 3
// OUTPUT:eq yes no len 4
// OUTPUT:find 1 missing yes
// OUTPUT:hash steady yes apart yes
// OUTPUT:copied unit 4
// OUTPUT:scope x 10 y 20 of 2
// OUTPUT:balanced
unit interns;
import std.io;
import std.sys;
import std.intern;
import std.map;
// One copy of every distinct name, and a number that stands for it. Comparing
// two names is comparing two integers; storing one costs four bytes and no
// ownership.
//
// There is deliberately no way to get a `str` back out: a borrow of the text
// would be a borrow of the interner, and the interner is exactly what a parser
// wants to keep adding to while it holds names.
fn run() -> !void {
var t: intern.Interner = try intern.Interner.with_capacity(8);
let a: intern.StrId = try t.intern("unit");
let b: intern.StrId = try t.intern("fn");
let c: intern.StrId = try t.intern("struct");
@print("ids {} {} {} count {}\n", a.raw, b.raw, c.raw, t.count_of());
// The same name twice is the same number, and costs nothing new.
let again: intern.StrId = try t.intern("unit");
@print("again {} same {} count {}\n", again.raw, yesno(a.same(again)),
t.count_of());
@print("eq {} {} len {}\n", yesno(t.eq(a, "unit")), yesno(t.eq(a, "fn")),
t.len_of(a));
@print("find {} missing {}\n", t.find("fn"),
yesno(t.find("nope") == intern.NONE));
// A name hashes the same every time, and two names do not collide here.
@print("hash steady {} apart {}\n", yesno(t.hash_of(a) == t.hash_of(again)),
yesno(t.hash_of(a) != t.hash_of(b)));
// The only way to see the text: copy it somewhere you own.
var buf: [8]u8 = undefined;
let n: usize = t.copy_into(a, buf[..]);
@print("copied {} {}\n", buf[0..n], n);
// A symbol table is a Map keyed on the name's number. std.map keys on
// bytes, so no separate integer-keyed map is needed.
var scope: map.Map(i32) = try map.Map(i32).with_capacity(8);
var key: [4]u8 = undefined;
try scope.put(intern.key_of(a, key[..]), 10);
try scope.put(intern.key_of(b, key[..]), 20);
@print("scope x {} y {} of {}\n", scope.get(intern.key_of(a, key[..]), -1),
scope.get(intern.key_of(b, key[..]), -1), scope.count_of());
return;
}
fn yesno(b: bool) -> []u8 {
if b { return "yes"; }
return "no";
}
fn main() -> i32 {
run() catch |e| { @print("failed\n"); return 1; };
if sys.allocs() == sys.frees() { @print("balanced\n"); }
else { @print("leaked\n"); }
return 0;
}