Skip to content

Commit f12900a

Browse files
authored
Clean up the interface hierarchy (#372)
* Restructure interfaces * Fix that * And this * CLEANER
1 parent 678425a commit f12900a

File tree

9 files changed

+133
-82
lines changed

9 files changed

+133
-82
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.black]
22
line-length = 88
3-
py36 = true
3+
target-version = ['py36']
44
include = '\.pyi?$'
55
exclude = '''
66
/(

src/basilisp/core/__init__.lpy

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,15 @@
621621
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
622622

623623
(defn deref
624-
"Dereference a delay or atom and returns its contents."
625-
[o]
626-
(basilisp.lang.runtime/deref o))
624+
"Dereference a delay or atom and returns its contents.
625+
If o is an object implementing IBlockingDeref and timeout-s and
626+
timeout-val are supplied, deref will wait at most timeout-s seconds,
627+
returning timeout-val if timeout-s seconds elapse and o has not
628+
returned."
629+
([o]
630+
(basilisp.lang.runtime/deref o))
631+
([o timeout-s timeout-val]
632+
(basilisp.lang.runtime/deref o timeout-s timeout-val)))
627633

628634
(defn compare-and-set!
629635
"Atomically set the value of atom to new-val if and only if old-val

src/basilisp/lang/delay.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
@attr.s(
1414
auto_attribs=True,
1515
frozen=True,
16-
these={"f": attr.ib(), "value": attr.ib(), "computed": attr.ib()},
16+
these={"f": attr.ib(), "value": attr.ib(), "computed": attr.ib(default=False)},
1717
)
1818
class _DelayState(Generic[T]):
1919
f: Callable[[], T]
2020
value: Optional[T]
21-
computed: bool = False
21+
computed: bool
2222

2323

2424
class Delay(IDeref[T]):

src/basilisp/lang/interfaces.py

Lines changed: 55 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -4,34 +4,24 @@
44

55
from basilisp.lang.obj import LispObject as _LispObject, seq_lrepr
66

7-
K = TypeVar("K")
8-
V = TypeVar("V")
7+
T = TypeVar("T")
98

109

11-
class IAssociative(Mapping[K, V]):
10+
class IDeref(Generic[T]):
1211
__slots__ = ()
1312

1413
@abstractmethod
15-
def assoc(self, *kvs) -> "IAssociative[K, V]":
16-
raise NotImplementedError()
17-
18-
@abstractmethod
19-
def contains(self, k: K) -> bool:
20-
raise NotImplementedError()
21-
22-
@abstractmethod
23-
def entry(self, k: K, default: Optional[V] = None) -> Optional[V]:
14+
def deref(self) -> Optional[T]:
2415
raise NotImplementedError()
2516

2617

27-
T = TypeVar("T")
28-
29-
30-
class IDeref(Generic[T]):
18+
class IBlockingDeref(IDeref[T]):
3119
__slots__ = ()
3220

3321
@abstractmethod
34-
def deref(self) -> Optional[T]:
22+
def deref(
23+
self, timeout: Optional[float] = None, timeout_val: Optional[T] = None
24+
) -> Optional[T]:
3525
raise NotImplementedError()
3626

3727

@@ -48,6 +38,10 @@ def data(self) -> "IPersistentMap":
4838
raise NotImplementedError()
4939

5040

41+
K = TypeVar("K")
42+
V = TypeVar("V")
43+
44+
5145
class IMapEntry(Generic[K, V]):
5246
__slots__ = ()
5347

@@ -78,7 +72,15 @@ def with_meta(self, meta: "IPersistentMap") -> "IMeta":
7872
ILispObject = _LispObject
7973

8074

81-
class IPersistentCollection(Generic[T]):
75+
class ISeqable(Iterable[T]):
76+
__slots__ = ()
77+
78+
@abstractmethod
79+
def seq(self) -> "ISeq[T]":
80+
raise NotImplementedError()
81+
82+
83+
class IPersistentCollection(ISeqable[T]):
8284
__slots__ = ()
8385

8486
@abstractmethod
@@ -91,6 +93,22 @@ def empty() -> "IPersistentCollection[T]":
9193
raise NotImplementedError()
9294

9395

96+
class IAssociative(Mapping[K, V], IPersistentCollection[IMapEntry[K, V]]):
97+
__slots__ = ()
98+
99+
@abstractmethod
100+
def assoc(self, *kvs) -> "IAssociative[K, V]":
101+
raise NotImplementedError()
102+
103+
@abstractmethod
104+
def contains(self, k: K) -> bool:
105+
raise NotImplementedError()
106+
107+
@abstractmethod
108+
def entry(self, k: K, default: Optional[V] = None) -> Optional[V]:
109+
raise NotImplementedError()
110+
111+
94112
class IPersistentStack(IPersistentCollection[T]):
95113
__slots__ = ()
96114

@@ -123,17 +141,31 @@ def disj(self, *elems: T) -> "IPersistentSet[T]":
123141
raise NotImplementedError()
124142

125143

144+
# MyPy has a lot of trouble dealing with the fact that Vectors are
145+
# considered as mapping types (from int -> T) and more traditional
146+
# sequential collections since the Python supertypes signatures conflict.
147+
# Below, we override the supertype signatures to select the signature
148+
# we specifically want to appear, but MyPy still complains. For now,
149+
# we will simply silence MyPy.
126150
class IPersistentVector( # type: ignore
127-
IAssociative[int, T], IPersistentStack[T], Sequence[T]
151+
Sequence[T], IAssociative[int, T], IPersistentStack[T]
128152
):
129153
__slots__ = ()
130154

155+
@abstractmethod
156+
def cons(self, *elems: T) -> "IPersistentVector[T]": # type: ignore
157+
raise NotImplementedError()
158+
159+
@abstractmethod
160+
def seq(self) -> "ISeq[T]": # type: ignore
161+
raise NotImplementedError()
162+
131163

132164
class IRecord(ABC):
133165
__slots__ = ()
134166

135167

136-
class ISeq(ILispObject, Iterable[T]):
168+
class ISeq(ILispObject, ISeqable[T]):
137169
__slots__ = ()
138170

139171
@property
@@ -155,6 +187,9 @@ def rest(self) -> "ISeq[T]":
155187
def cons(self, elem: T) -> "ISeq[T]":
156188
raise NotImplementedError()
157189

190+
def seq(self) -> "ISeq[T]":
191+
return self
192+
158193
def _lrepr(self, **kwargs):
159194
return seq_lrepr(iter(self), "(", ")", **kwargs)
160195

@@ -174,12 +209,5 @@ def __iter__(self):
174209
o = o.rest
175210

176211

177-
class ISeqable(ABC, Iterable[T]):
178-
__slots__ = ()
179-
180-
def seq(self) -> ISeq[T]:
181-
raise NotImplementedError()
182-
183-
184212
class IType(ABC):
185213
__slots__ = ()

src/basilisp/lang/list.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,13 @@ def pop(self) -> "List":
8585

8686
def list(members, meta=None) -> List: # pylint:disable=redefined-builtin
8787
"""Creates a new list."""
88-
return List(plist(iterable=members), meta=meta)
88+
return List( # pylint: disable=abstract-class-instantiated
89+
plist(iterable=members), meta=meta
90+
)
8991

9092

9193
def l(*members, meta=None) -> List:
9294
"""Creates a new list from members."""
93-
return List(plist(iterable=members), meta=meta)
95+
return List( # pylint: disable=abstract-class-instantiated
96+
plist(iterable=members), meta=meta
97+
)

src/basilisp/lang/map.py

Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,7 @@
88
pvector,
99
)
1010

11-
from basilisp.lang.interfaces import (
12-
ILispObject,
13-
IMapEntry,
14-
IMeta,
15-
IPersistentCollection,
16-
IPersistentMap,
17-
ISeq,
18-
ISeqable,
19-
)
11+
from basilisp.lang.interfaces import ILispObject, IMapEntry, IMeta, IPersistentMap, ISeq
2012
from basilisp.lang.obj import map_lrepr as _map_lrepr
2113
from basilisp.lang.seq import sequence
2214
from basilisp.lang.vector import Vector
@@ -56,13 +48,7 @@ def from_vec(v: Sequence[Union[K, V]]) -> "MapEntry[K, V]":
5648
return MapEntry(pvector(v))
5749

5850

59-
class Map(
60-
IPersistentCollection[MapEntry[K, V]],
61-
ILispObject,
62-
IMeta,
63-
ISeqable[MapEntry[K, V]],
64-
IPersistentMap[K, V],
65-
):
51+
class Map(ILispObject, IMeta, IPersistentMap[K, V]):
6652
"""Basilisp Map. Delegates internally to a pyrsistent.PMap object.
6753
Do not instantiate directly. Instead use the m() and map() factory
6854
methods below."""
@@ -155,8 +141,11 @@ def update_with(
155141

156142
def cons(
157143
self,
158-
*elems: Union["Map[K, V]", Dict[K, V], MapEntry[K, V], Vector[Union[K, V]]],
144+
*elems: Union["Map[K, V]", Dict[K, V], IMapEntry[K, V], Vector[Union[K, V]]],
159145
) -> "Map[K, V]":
146+
# For now, this definition does not take the generic Mapping[K, V] type
147+
# because Vectors are technically Mapping[int, V] types, so this would
148+
# require restructuring of the logic.
160149
e = self._inner.evolver()
161150
try:
162151
for elem in elems:
@@ -166,7 +155,7 @@ def cons(
166155
elif isinstance(elem, dict):
167156
for k, v in elem.items():
168157
e.set(k, v)
169-
elif isinstance(elem, MapEntry):
158+
elif isinstance(elem, IMapEntry):
170159
e.set(elem.key, elem.value)
171160
else:
172161
entry = MapEntry.from_vec(elem)
@@ -181,7 +170,7 @@ def cons(
181170
def empty() -> "Map":
182171
return m()
183172

184-
def seq(self) -> ISeq[MapEntry[K, V]]:
173+
def seq(self) -> ISeq[IMapEntry[K, V]]:
185174
return sequence(self)
186175

187176

0 commit comments

Comments
 (0)