/
memo.py
45 lines (37 loc) · 1.38 KB
/
memo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def memoize(func):
"""Memoize a parsing method.
The functon must be a method on a class deriving from Parser.
The method must have either no arguments or a single argument that
is an int or str (the latter being the case for expect()).
It must return either None or an object that is not modified (at
least not while we're parsing).
We memoize positive and negative outcomes per input position.
The function is expected to move the input position iff it returns
a not-None value.
The memo is structured as a dict of dict, the outer dict indexed
by input position, the inner by function and arguments.
"""
def memoize_wrapper(self, *args):
vis = self.tokenizer.vis
pos = self.mark()
if vis is not None:
vis.show_call(pos, func.__name__, args)
memo = self.memos.get(pos)
if memo is None:
memo = self.memos[pos] = {}
key = (func, args)
if key in memo:
res, endpos = memo[key]
self.reset(endpos)
else:
res = func(self, *args)
endpos = self.mark()
if res is None:
assert endpos == pos
else:
assert endpos > pos
memo[key] = res, endpos
if vis is not None:
vis.show_return(pos, res, endpos)
return res
return memoize_wrapper