Skip to content

Commit 89f7091

Browse files
committed
rewrite memoization
1 parent 2eb5714 commit 89f7091

File tree

1 file changed

+16
-57
lines changed

1 file changed

+16
-57
lines changed

src/parser/parser_lib.ts

Lines changed: 16 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,34 @@
11
import { assertGreater } from "@std/assert/greater";
2-
import { memoize } from "@std/cache/memoize";
2+
import { MemoizationCacheResult, memoize } from "@std/cache/memoize";
33
import { ArrayResult, ArrayResultError } from "../array_result.ts";
44

55
type Input = Readonly<{ source: string; position: number }>;
66
type ParserResult<T> = ArrayResult<Readonly<{ value: T; length: number }>>;
77
type InnerParser<T> = (input: Input) => ParserResult<T>;
8+
type Memo<T> = Map<number, MemoizationCacheResult<ParserResult<T>>>;
89

9-
let source = "";
10-
const allMemo: Set<WeakRef<SourceMemo<unknown>>> = new Set();
10+
const allMemo: Set<WeakRef<Memo<unknown>>> = new Set();
1111

12-
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-
}
22-
class SourceMemo<T> {
23-
readonly #map: Map<number, T> = new Map();
24-
constructor() {
25-
allMemo.add(new WeakRef(this));
26-
}
27-
set(key: Input, value: T): void {
28-
if (source !== key.source) {
29-
source = key.source;
30-
clearCache();
31-
}
32-
this.#map.set(key.position, value);
33-
}
34-
get(key: Input): undefined | T {
35-
if (source === key.source) {
36-
return this.#map.get(key.position);
37-
} else {
38-
return undefined;
39-
}
40-
}
41-
has(key: Input): boolean {
42-
return source === key.source && this.#map.has(key.position);
43-
}
44-
delete(key: Input): void {
45-
if (source === key.source) {
46-
this.#map.delete(key.position);
47-
}
48-
}
49-
clear(): void {
50-
this.#map.clear();
51-
}
52-
}
5312
export class Parser<T> {
5413
readonly rawParser: InnerParser<T>;
5514
constructor(parser: InnerParser<T>) {
56-
// Turns out @std/[email protected] is buggy
57-
const cache: SourceMemo<ParserResult<T>> = new SourceMemo();
15+
const cache: Memo<T> = new Map();
5816
allMemo.add(new WeakRef(cache));
59-
this.rawParser = (input) => {
60-
if (cache.has(input)) {
61-
return cache.get(input)!;
62-
} else {
63-
const result = parser(input);
64-
cache.set(input, result);
65-
return result;
66-
}
67-
};
17+
this.rawParser = memoize<InnerParser<T>, number, Memo<T>>(
18+
parser,
19+
{ getKey: ({ position }) => position, cache },
20+
);
6821
}
6922
generateParser(): (source: string) => ArrayResult<T> {
7023
return (input) => {
71-
source = input;
72-
clearCache();
24+
for (const memo of allMemo) {
25+
const ref = memo.deref();
26+
if (ref == null) {
27+
allMemo.delete(memo);
28+
} else {
29+
ref.clear();
30+
}
31+
}
7332
return this.rawParser({ source: input, position: 0 })
7433
.map(({ value }) => value);
7534
};

0 commit comments

Comments
 (0)