Files
doslang-mirror/fec/tests/exec/maps.fe
T
coolguy 8c4e80e246 std: map 을 쓴다 -- 바이트 열에서 값으로
컴파일러는 이름을 끊임없이 찾는데 리스트 선형 탐색은 그 모양이 아니다. 키는
맵이 소유하는 한 버퍼에 복사되고 슬롯은 그 안의 어디인지만 적는다 -- R11 이
말하는 아레나와 핸들 모양이고, 그래서 맵을 놓는 것이 엔트리마다 하나가 아니라
두 번의 해제다.

개방 주소법에 선형 탐사. 표는 2의 거듭제곱이라 나눗셈이 아니라 마스크이고,
탐사가 길어지는 것이 표가 차는 것보다 먼저라 3/4 에서 자란다.

길에서 고친 것 넷:

- 인스턴스를 만들 때 선언 유닛으로 전환하지 않아서, 필드 타입 Slot(V) 를
  호출자 유닛에서 찾고 있었다.
- mem.alloc_slice 가 원소 타입으로 단순한 이름만 받았다. Slot(V) 같은
  인스턴스도 받는다.
- 쓸 수 있는지를 바인딩이 아니라 소유된 것이 정한다. let p: ^[]mut T 는 p 를
  고정하고 그것이 소유한 것은 쓸 수 있게 둔다. 슬라이스 인덱스도 마찬가지다.
- 메서드 인자에 자유 함수와 같은 호출 한정 약화가 없었다.

알게 된 것: 대여는 루트 단위라 self 의 한 필드에 쓰는 동안 다른 필드를 읽을 수
없다. 지역으로 빼거나 메서드를 나누면 되지만, 필드 단위 대여가 있으면 훨씬
편할 자리다.

  count 5 / fn 2 let 3 missing 0 / grown 64 / after 40 / balanced

218/218, 28/28.
2026-08-17 12:23:52 +09:00

49 lines
1.3 KiB
Plaintext

// EXIT:0
// OUTPUT:count 5
// OUTPUT:fn 2 let 3 missing 0
// OUTPUT:grown 64
// OUTPUT:after 40
// OUTPUT:balanced
unit maps;
import std.io;
import std.map;
import std.fmt;
import std.sys;
fn run() -> !void {
var seen: map.Map(i32) = try map.Map(i32).with_capacity(4);
try seen.put("unit", 1);
try seen.put("fn", 2);
try seen.put("let", 3);
try seen.put("struct", 4);
try seen.put("return", 5);
@print("count {}\n", seen.count_of());
@print("fn {} let {} missing {}\n", seen.get("fn", 0), seen.get("let", 0),
seen.get("nope", 0));
// Enough keys to make it grow more than once.
var buf: [8]u8 = undefined;
var i: usize = 0;
while i < 40 {
let n: usize = fmt.fmt_i32(buf[..], i as i32);
try seen.put(buf[0..n], (i as i32) + 100);
i = i + 1;
}
@print("grown {}\n", seen.room());
var found: usize = 0;
i = 0;
while i < 40 {
let n: usize = fmt.fmt_i32(buf[..], i as i32);
if seen.get(buf[0..n], 0) == (i as i32) + 100 { found = found + 1; }
i = i + 1;
}
@print("after {}\n", found);
return;
}
fn main() -> i32 {
run() catch |e| { @print("failed\n"); return 1; };
if sys.allocs() != sys.frees() { @print("leaked\n"); return 2; }
@print("balanced\n");
return 0;
}