|
22 | 22 |
|
23 | 23 | from abc import ABC, abstractmethod
|
24 | 24 | import pymbolic.primitives as primitives
|
| 25 | +from typing import Generic, TypeVar, Any, Dict |
25 | 26 |
|
26 | 27 | __doc__ = """
|
27 | 28 | Basic dispatch
|
|
73 | 74 | .. autoclass:: CSECachingMapperMixin
|
74 | 75 | """
|
75 | 76 |
|
| 77 | +CachedMapperT = TypeVar("CachedMapperT") # used in CachedMapper |
| 78 | + |
76 | 79 |
|
77 | 80 | try:
|
78 | 81 | import numpy
|
@@ -200,6 +203,34 @@ def map_foreign(self, expr, *args, **kwargs):
|
200 | 203 | RecursiveMapper = Mapper
|
201 | 204 |
|
202 | 205 |
|
| 206 | +# {{{ CachedMapper |
| 207 | + |
| 208 | +class CachedMapper(Mapper, Generic[CachedMapperT]): |
| 209 | + """Mapper class that maps each subexpression exactly once. This loses some |
| 210 | + information compared to :class:`Mapper` as a subexpression is visited only from |
| 211 | + one of its predecessors. |
| 212 | + """ |
| 213 | + |
| 214 | + def __init__(self) -> None: |
| 215 | + self._cache: Dict[CachedMapperT, Any] = {} |
| 216 | + |
| 217 | + def cache_key(self, expr: CachedMapperT) -> Any: |
| 218 | + return expr |
| 219 | + |
| 220 | + # type-ignore-reason: incompatible with super class |
| 221 | + # type: ignore[override] |
| 222 | + def rec(self, expr: CachedMapperT, *args, **kwargs) -> Any: |
| 223 | + key = self.cache_key(expr) |
| 224 | + try: |
| 225 | + return self._cache[key] |
| 226 | + except KeyError: |
| 227 | + result = super().rec(expr, *args, **kwargs) # type: ignore[type-var] |
| 228 | + self._cache[key] = result |
| 229 | + return result |
| 230 | + |
| 231 | +# }}} |
| 232 | + |
| 233 | + |
203 | 234 | # {{{ combine mapper
|
204 | 235 |
|
205 | 236 | class CombineMapper(RecursiveMapper):
|
@@ -364,7 +395,7 @@ def map_constant(self, expr):
|
364 | 395 |
|
365 | 396 | # {{{ identity mapper
|
366 | 397 |
|
367 |
| -class IdentityMapper(Mapper): |
| 398 | +class IdentityMapper(CachedMapper): |
368 | 399 | """A :class:`Mapper` whose default mapper methods
|
369 | 400 | make a deep copy of each subexpression.
|
370 | 401 |
|
|
0 commit comments