-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathaliases.py
More file actions
69 lines (49 loc) · 1.77 KB
/
Copy pathaliases.py
File metadata and controls
69 lines (49 loc) · 1.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#!/usr/bin/python3
"""Alias implementations"""
from __future__ import annotations
from abc import abstractmethod
from collections import OrderedDict
from collections.abc import MutableMapping, Iterator
from typing import TypeVar, Type
from lambda_calculus.terms import Term
from lambda_calculus.visitors.substitution import Substitution
__all__ = (
"Aliases",
"LetAliases"
)
V = TypeVar("V")
class Aliases(MutableMapping[V, Term[V]]):
"""ABC for alias implementations"""
__slots__ = ()
@abstractmethod
def apply(self, term: Term[V]) -> Term[V]:
"""apply the aliases to a term"""
raise NotImplementedError()
class LetAliases(Aliases[V]):
"""Alias implementations with no self reference"""
aliases: OrderedDict[V, Term[V]]
substitution: Type[Substitution[V]]
__slots__ = (
"aliases",
"substitution"
)
def __init__(self, substitution: Type[Substitution[V]]) -> None:
self.aliases = OrderedDict()
self.substitution = substitution
def __len__(self) -> int:
return len(self.aliases)
def __iter__(self) -> Iterator[V]:
return iter(self.aliases)
def __getitem__(self, alias: V) -> Term[V]:
return self.aliases[alias]
def __setitem__(self, alias: V, term: Term[V]) -> None:
self.aliases[alias] = self.apply(term)
self.aliases.move_to_end(alias, last=True)
def __delitem__(self, alias: V) -> None:
del self.aliases[alias]
def apply(self, term: Term[V]) -> Term[V]:
"""apply the aliases to a term"""
# dont substitute free variables with later defined aliases
for alias, value in reversed(self.aliases.items()):
term = term.accept(self.substitution.from_substitution(alias, value))
return term