type5 is much more first principles based, so we get a lot of weird quirks removed: - FromLiteral no longer needs to understand AST - Type unifications works more like Haskell - Function types are just ordinary types, saving a lot of manual busywork and more.
47 lines
1.4 KiB
Python
47 lines
1.4 KiB
Python
from typing import Any, Callable, Iterable, Mapping
|
|
|
|
from ..type5 import typeexpr as type5typeexpr
|
|
|
|
|
|
class TypeVariableRouter[G]:
|
|
__slots__ = ('data', 'variables',)
|
|
|
|
data: dict[
|
|
tuple[type5typeexpr.TypeExpr, ...],
|
|
Callable[[G, dict[type5typeexpr.TypeVariable, type5typeexpr.TypeExpr]], None],
|
|
]
|
|
variables: tuple[type5typeexpr.TypeVariable, ...]
|
|
|
|
def __init__(self, variables: Iterable[type5typeexpr.TypeVariable]) -> None:
|
|
self.data = {}
|
|
self.variables = tuple(variables)
|
|
|
|
assert len(self.variables) == len(set(self.variables))
|
|
|
|
def register(
|
|
self,
|
|
types_it: Iterable[type5typeexpr.TypeExpr],
|
|
implementation: Callable[[G, Any], None],
|
|
) -> None:
|
|
types = tuple(types_it)
|
|
|
|
assert all(
|
|
v.kind == t.kind and type5typeexpr.is_concrete(t)
|
|
for v, t in zip(self.variables, types, strict=True)
|
|
), (self.variables, types_it, )
|
|
|
|
self.data[types] = implementation
|
|
|
|
def __call__(
|
|
self,
|
|
lookup: Mapping[type5typeexpr.TypeVariable, type5typeexpr.TypeExpr],
|
|
) -> Callable[[G, Any], None]:
|
|
types = tuple(lookup[v] for v in self.variables)
|
|
|
|
assert all(
|
|
v.kind == t.kind and type5typeexpr.is_concrete(t)
|
|
for v, t in zip(self.variables, types, strict=True)
|
|
), (self.variables, lookup, )
|
|
|
|
return self.data[types]
|