Add Tree as a possible way to allow construction of whole subtrees at once

This commit is contained in:
Jan Petykiewicz 2023-01-30 17:27:42 -08:00
parent 7191e5f62c
commit 454f167340

View File

@ -11,6 +11,7 @@ import logging
import base64 import base64
import struct import struct
import re import re
import copy
from pprint import pformat from pprint import pformat
from collections import defaultdict from collections import defaultdict
from abc import ABCMeta, abstractmethod from abc import ABCMeta, abstractmethod
@ -413,7 +414,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
#def __getitem__(self, key: str) -> 'Pattern': #def __getitem__(self, key: str) -> 'Pattern':
#def __iter__(self) -> Iterator[str]: #def __iter__(self) -> Iterator[str]:
#def __len__(self) -> int: #def __len__(self) -> int:
#def __setitem__(self, key: str, value: 'Pattern') -> None: #def __setitem__(self, key: str, value: Union['Pattern', Callable[[], 'Pattern']]) -> None:
#def __delitem__(self, key: str) -> None: #def __delitem__(self, key: str) -> None:
@abstractmethod @abstractmethod
@ -432,7 +433,12 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
def _merge(self, key_self: str, other: Mapping[str, 'Pattern'], key_other: str) -> None: def _merge(self, key_self: str, other: Mapping[str, 'Pattern'], key_other: str) -> None:
pass pass
def rename(self: ML, old_name: str, new_name: str) -> ML: def rename(
self: ML,
old_name: str,
new_name: str,
move_references: bool = False,
) -> ML:
""" """
Rename a pattern. Rename a pattern.
@ -445,6 +451,8 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
""" """
self[new_name] = self[old_name] self[new_name] = self[old_name]
del self[old_name] del self[old_name]
if move_references:
self.move_references(old_name, new_name)
return self return self
def move_references(self: ML, old_target: str, new_target: str) -> ML: def move_references(self: ML, old_target: str, new_target: str) -> ML:
@ -540,8 +548,7 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
temp = WrapLibrary(copy.deepcopy(dict(other))) # Copy and turn into a mutable library temp = WrapLibrary(copy.deepcopy(dict(other))) # Copy and turn into a mutable library
for old_name, new_name in rename_map.items(): for old_name, new_name in rename_map.items():
temp.rename(old_name, new_name) temp.rename(old_name, new_name, move_references=True)
temp.move_references(old_name, new_name)
else: else:
for key in other.keys(): for key in other.keys():
@ -549,6 +556,29 @@ class MutableLibrary(Library, MutableMapping[str, 'Pattern'], metaclass=ABCMeta)
return self return self
def add_tree(
self: ML,
name: str,
tree: 'Tree',
rename_theirs: Callable[['Library', str], str] = _rename_patterns,
) -> ML:
"""
Add a `Tree` object into the current library.
Args:
name: New name for the top-level pattern.
tree: The `Tree` object (a `Library` with a specified `top` Pattern)
which will be added into the current library.
rename_theirs: Called as rename_theirs(self, name) for each duplicate name
encountered in `other`. Should return the new name for the pattern in
`other`.
Default is effectively
`name.split('$')[0] if name.startswith('_') else name`
"""
tree.library.rename(tree.top, name, move_references=True)
self.add(tree.library, rename_theirs=rename_theirs)
return self
def dedup( def dedup(
self: ML, self: ML,
norm_value: int = int(1e6), norm_value: int = int(1e6),
@ -871,13 +901,21 @@ class LazyLibrary(MutableLibrary):
def __repr__(self) -> str: def __repr__(self) -> str:
return '<LazyLibrary with keys\n' + pformat(list(self.keys())) + '>' return '<LazyLibrary with keys\n' + pformat(list(self.keys())) + '>'
def rename(self: LL, old_name: str, new_name: str) -> LL: def rename(
self: LL,
old_name: str,
new_name: str,
move_references: bool = False,
) -> LL:
""" """
Rename a pattern. Rename a pattern.
Args: Args:
old_name: Current name for the pattern old_name: Current name for the pattern
new_name: New name for the pattern new_name: New name for the pattern
move_references: Whether to scan all refs in the pattern and
move them to point to `new_name` as necessary.
Default `False`.
Returns: Returns:
self self
@ -886,6 +924,10 @@ class LazyLibrary(MutableLibrary):
if old_name in self.cache: if old_name in self.cache:
self.cache[new_name] = self.cache[old_name] self.cache[new_name] = self.cache[old_name]
del self[old_name] del self[old_name]
if move_references:
self.move_references(old_name, new_name)
return self return self
def move_references(self: LL, old_target: str, new_target: str) -> LL: def move_references(self: LL, old_target: str, new_target: str) -> LL:
@ -937,6 +979,33 @@ class AbstractView(Mapping[str, Abstract]):
return self.library.__len__() return self.library.__len__()
class Tree(MutableLibrary):
top: str
library: MutableLibrary
@property
def pattern(self) -> Pattern:
return self.library[self.top]
def __init__(self, top: Union[str, NamedPattern], library: MutableLibrary) -> None:
self.top = top if isinstance(top, str) else top.name
self.library = library
def __getitem__(self, key: str) -> 'Pattern':
return self.library[key]
def __iter__(self) -> Iterator[str]:
return iter(self.library)
def __len__(self) -> int:
return len(self.library)
def __setitem__(self, key: str, value: Union['Pattern', Callable[[], 'Pattern']]) -> None:
self.library[key] = value
def __delitem__(self, key: str) -> None:
del self.library[key]
def _rename_patterns(lib: Library, name: str) -> str: def _rename_patterns(lib: Library, name: str) -> str:
# TODO document rename function # TODO document rename function