Skip to content

Commit 0579aae

Browse files
committed
improve memoization
1 parent b0d7994 commit 0579aae

File tree

1 file changed

+28
-25
lines changed

1 file changed

+28
-25
lines changed

src/parser/parser_lib.ts

Lines changed: 28 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,49 +6,50 @@ type Source = Readonly<{ source: string; position: number }>;
66
type ParserResult<T> = ArrayResult<Readonly<{ value: T; size: number }>>;
77
type InnerParser<T> = (input: Source) => ParserResult<T>;
88

9+
let source = "";
10+
const allMemo: Set<WeakRef<SourceMemo<unknown>>> = new Set();
11+
12+
export function clearCache(): void {
13+
for (const memo of allMemo) {
14+
const ref = memo.deref();
15+
if (ref == null) {
16+
allMemo.delete(memo);
17+
} else {
18+
ref.clear();
19+
}
20+
}
21+
}
922
class SourceMemo<T> {
10-
#source = "";
1123
readonly #map: Map<number, T> = new Map();
24+
constructor() {
25+
allMemo.add(new WeakRef(this));
26+
}
1227
set(key: Source, value: T): void {
13-
if (this.#source !== key.source) {
14-
this.#source = key.source;
15-
this.clear();
28+
if (source !== key.source) {
29+
source = key.source;
30+
clearCache();
1631
}
1732
this.#map.set(key.position, value);
1833
}
1934
get(key: Source): undefined | T {
20-
if (this.#source === key.source) {
35+
if (source === key.source) {
2136
return this.#map.get(key.position);
2237
} else {
2338
return undefined;
2439
}
2540
}
2641
has(key: Source): boolean {
27-
return this.#source === key.source && this.#map.has(key.position);
42+
return source === key.source && this.#map.has(key.position);
2843
}
2944
delete(key: Source): void {
30-
if (this.#source === key.source) {
45+
if (source === key.source) {
3146
this.#map.delete(key.position);
3247
}
3348
}
3449
clear(): void {
3550
this.#map.clear();
3651
}
3752
}
38-
type SourceMemoResult<T> = SourceMemo<MemoizationCacheResult<ParserResult<T>>>;
39-
40-
const caches: Set<WeakRef<SourceMemo<unknown>>> = new Set();
41-
42-
export function clearCache(): void {
43-
for (const memo of caches) {
44-
const ref = memo.deref();
45-
if (ref == null) {
46-
caches.delete(memo);
47-
} else {
48-
ref.clear();
49-
}
50-
}
51-
}
5253
export class Parser<T> {
5354
readonly rawParser: InnerParser<T>;
5455
constructor(parser: InnerParser<T>) {
@@ -57,11 +58,13 @@ export class Parser<T> {
5758
assert(source.source.length >= source.position);
5859
return parser(source);
5960
};
60-
const cache: SourceMemoResult<T> = new SourceMemo();
61-
caches.add(new WeakRef(cache));
62-
this.rawParser = memoize<InnerParser<T>, Source, SourceMemoResult<T>>(
61+
this.rawParser = memoize<
62+
InnerParser<T>,
63+
Source,
64+
SourceMemo<MemoizationCacheResult<ParserResult<T>>>
65+
>(
6366
ensureParser,
64-
{ cache },
67+
{ cache: new SourceMemo() },
6568
);
6669
}
6770
generateParser(): (source: string) => ArrayResult<T> {

0 commit comments

Comments
 (0)