Skip to content

Commit c1bdbe8

Browse files
gh-124889: Rework Python generator cache (#125816)
1 parent 4efe64a commit c1bdbe8

File tree

1 file changed

+48
-27
lines changed

1 file changed

+48
-27
lines changed

Tools/peg_generator/pegen/python_generator.py

+48-27
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import os.path
22
import token
3-
from typing import IO, Any, Dict, Optional, Sequence, Set, Text, Tuple
3+
from typing import IO, Any, Callable, Dict, Optional, Sequence, Set, Text, Tuple
44

55
from pegen import grammar
66
from pegen.grammar import (
@@ -93,7 +93,7 @@ def visit_Forced(self, node: Forced) -> bool:
9393
class PythonCallMakerVisitor(GrammarVisitor):
9494
def __init__(self, parser_generator: ParserGenerator):
9595
self.gen = parser_generator
96-
self.cache: Dict[Any, Any] = {}
96+
self.cache: Dict[str, Tuple[str, str]] = {}
9797

9898
def visit_NameLeaf(self, node: NameLeaf) -> Tuple[Optional[str], str]:
9999
name = node.value
@@ -110,16 +110,6 @@ def visit_NameLeaf(self, node: NameLeaf) -> Tuple[Optional[str], str]:
110110
def visit_StringLeaf(self, node: StringLeaf) -> Tuple[str, str]:
111111
return "literal", f"self.expect({node.value})"
112112

113-
def visit_Rhs(self, node: Rhs) -> Tuple[Optional[str], str]:
114-
if node in self.cache:
115-
return self.cache[node]
116-
if len(node.alts) == 1 and len(node.alts[0].items) == 1:
117-
self.cache[node] = self.visit(node.alts[0].items[0])
118-
else:
119-
name = self.gen.artificial_rule_from_rhs(node)
120-
self.cache[node] = name, f"self.{name}()"
121-
return self.cache[node]
122-
123113
def visit_NamedItem(self, node: NamedItem) -> Tuple[Optional[str], str]:
124114
name, call = self.visit(node.item)
125115
if node.name:
@@ -151,26 +141,57 @@ def visit_Opt(self, node: Opt) -> Tuple[str, str]:
151141
else:
152142
return "opt", f"{call},"
153143

144+
def _generate_artificial_rule_call(
145+
self,
146+
node: Any,
147+
prefix: str,
148+
call_by_name_func: Callable[[str], str],
149+
rule_generation_func: Callable[[], str],
150+
) -> Tuple[str, str]:
151+
node_str = f"{node}"
152+
key = f"{prefix}_{node_str}"
153+
if key in self.cache:
154+
return self.cache[key]
155+
156+
name = rule_generation_func()
157+
call = call_by_name_func(name)
158+
self.cache[key] = name, call
159+
return self.cache[key]
160+
161+
def visit_Rhs(self, node: Rhs) -> Tuple[str, str]:
162+
if len(node.alts) == 1 and len(node.alts[0].items) == 1:
163+
return self.visit(node.alts[0].items[0])
164+
165+
return self._generate_artificial_rule_call(
166+
node,
167+
"rhs",
168+
lambda name: f"self.{name}()",
169+
lambda: self.gen.artificial_rule_from_rhs(node),
170+
)
171+
154172
def visit_Repeat0(self, node: Repeat0) -> Tuple[str, str]:
155-
if node in self.cache:
156-
return self.cache[node]
157-
name = self.gen.artificial_rule_from_repeat(node.node, False)
158-
self.cache[node] = name, f"self.{name}()," # Also a trailing comma!
159-
return self.cache[node]
173+
return self._generate_artificial_rule_call(
174+
node,
175+
"repeat0",
176+
lambda name: f"self.{name}(),", # Also a trailing comma!
177+
lambda: self.gen.artificial_rule_from_repeat(node.node, is_repeat1=False),
178+
)
160179

161180
def visit_Repeat1(self, node: Repeat1) -> Tuple[str, str]:
162-
if node in self.cache:
163-
return self.cache[node]
164-
name = self.gen.artificial_rule_from_repeat(node.node, True)
165-
self.cache[node] = name, f"self.{name}()" # But no trailing comma here!
166-
return self.cache[node]
181+
return self._generate_artificial_rule_call(
182+
node,
183+
"repeat1",
184+
lambda name: f"self.{name}()", # But no trailing comma here!
185+
lambda: self.gen.artificial_rule_from_repeat(node.node, is_repeat1=True),
186+
)
167187

168188
def visit_Gather(self, node: Gather) -> Tuple[str, str]:
169-
if node in self.cache:
170-
return self.cache[node]
171-
name = self.gen.artificial_rule_from_gather(node)
172-
self.cache[node] = name, f"self.{name}()" # No trailing comma here either!
173-
return self.cache[node]
189+
return self._generate_artificial_rule_call(
190+
node,
191+
"gather",
192+
lambda name: f"self.{name}()", # No trailing comma here either!
193+
lambda: self.gen.artificial_rule_from_gather(node),
194+
)
174195

175196
def visit_Group(self, node: Group) -> Tuple[Optional[str], str]:
176197
return self.visit(node.rhs)

0 commit comments

Comments
 (0)