ef8c36c3533aaf66cca867a36b0913ae92281bb1
[bigint-presentation-code.git] / src / bigint_presentation_code / util.py
1 from typing import (TYPE_CHECKING, AbstractSet, Any, Iterable, Iterator,
2 Mapping, MutableSet, NoReturn, TypeVar, Union)
3
4 if TYPE_CHECKING:
5 from typing_extensions import Literal, Self, final
6 else:
7 def final(v):
8 return v
9
10 class _Literal:
11 def __getitem__(self, v):
12 if isinstance(v, tuple):
13 return Union[tuple(type(i) for i in v)]
14 return type(v)
15
16 Literal = _Literal()
17
18 Self = Any
19
20 _T_co = TypeVar("_T_co", covariant=True)
21 _T = TypeVar("_T")
22
23 __all__ = ["final", "Literal", "Self", "assert_never", "OFSet", "OSet", "FMap"]
24
25
26 # pyright currently doesn't like typing_extensions' definition
27 # -- added to typing in python 3.11
28 def assert_never(arg):
29 # type: (NoReturn) -> NoReturn
30 raise AssertionError("got to code that's supposed to be unreachable")
31
32
33 class OFSet(AbstractSet[_T_co]):
34 """ ordered frozen set """
35 __slots__ = "__items",
36
37 def __init__(self, items=()):
38 # type: (Iterable[_T_co]) -> None
39 self.__items = {v: None for v in items}
40
41 def __contains__(self, x):
42 return x in self.__items
43
44 def __iter__(self):
45 return iter(self.__items)
46
47 def __len__(self):
48 return len(self.__items)
49
50 def __hash__(self):
51 return self._hash()
52
53 def __repr__(self):
54 if len(self) == 0:
55 return "OFSet()"
56 return f"OFSet({list(self)})"
57
58
59 class OSet(MutableSet[_T]):
60 """ ordered mutable set """
61 __slots__ = "__items",
62
63 def __init__(self, items=()):
64 # type: (Iterable[_T]) -> None
65 self.__items = {v: None for v in items}
66
67 def __contains__(self, x):
68 return x in self.__items
69
70 def __iter__(self):
71 return iter(self.__items)
72
73 def __len__(self):
74 return len(self.__items)
75
76 def add(self, value):
77 # type: (_T) -> None
78 self.__items[value] = None
79
80 def discard(self, value):
81 # type: (_T) -> None
82 self.__items.pop(value, None)
83
84 def __repr__(self):
85 if len(self) == 0:
86 return "OSet()"
87 return f"OSet({list(self)})"
88
89
90 class FMap(Mapping[_T, _T_co]):
91 """ordered frozen hashable mapping"""
92 __slots__ = "__items", "__hash"
93
94 def __init__(self, items=()):
95 # type: (Mapping[_T, _T_co] | Iterable[tuple[_T, _T_co]]) -> None
96 self.__items = dict(items) # type: dict[_T, _T_co]
97 self.__hash = None # type: None | int
98
99 def __getitem__(self, item):
100 # type: (_T) -> _T_co
101 return self.__items[item]
102
103 def __iter__(self):
104 # type: () -> Iterator[_T]
105 return iter(self.__items)
106
107 def __len__(self):
108 return len(self.__items)
109
110 def __eq__(self, other):
111 # type: (object) -> bool
112 if isinstance(other, FMap):
113 return self.__items == other.__items
114 return super().__eq__(other)
115
116 def __hash__(self):
117 if self.__hash is None:
118 self.__hash = hash(frozenset(self.items()))
119 return self.__hash
120
121 def __repr__(self):
122 return f"FMap({self.__items})"