Skip to content

Commit

Permalink
Experimental support for sealed class
Browse files Browse the repository at this point in the history
Related to jspahrsummers#45
  • Loading branch information
adsharma committed May 27, 2021
1 parent ef089c4 commit 1a700f1
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
{
"editor.formatOnPaste": true,
"editor.formatOnSave": true,
"python.formatting.provider": "yapf",
"python.formatting.provider": "black",
"python.linting.mypyArgs": [
"--strict",
"--ignore-missing-imports",
"--implicit-reexport",
"--follow-imports=silent",
"--show-column-numbers"
],
"python.pythonPath": "venv/bin/python3",
"python.testing.unittestArgs": [
"-v",
"-s",
Expand Down
25 changes: 17 additions & 8 deletions adt/decorator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,18 @@
# mypy: no-warn-unused-ignores
from enum import Enum
from typing import Any, Callable, Type, TypeVar, no_type_check
from typing import Any, Callable, Tuple, Type, TypeVar, no_type_check

from adt.case import CaseConstructor
from adt.case import CaseConstructor, Case


def get_case(type_obj):
if isinstance(type_obj, type):
return Case[type_obj]
if type_obj is None:
return Case
if type_obj._name == "Tuple":
return Case[type_obj.__args__]
return Case


@no_type_check
Expand All @@ -14,8 +24,8 @@ def adt(cls):
return cls

caseConstructors = {
k: constructor
for k, constructor in annotations.items()
k: get_case(typename)
for k, typename in annotations.items()
if not k.startswith("__")
}

Expand All @@ -25,9 +35,7 @@ def adt(cls):
f"Annotation {k} should be a Case[…] constructor, got {constructor!r} instead"
)

cls._Key = Enum( # type: ignore
"_Key", list(caseConstructors.keys())
)
cls._Key = Enum("_Key", list(caseConstructors.keys())) # type: ignore

cls._types = list(x.getTypes() for x in list(caseConstructors.values()))

Expand Down Expand Up @@ -107,7 +115,8 @@ def _hash(self: Any) -> int:
def _installOneConstructor(cls: Any, case: Enum) -> None:
def constructor(cls: Type[Any], *args: Any, _case: Enum = case) -> Any:
return cls(
key=_case, value=cls.__annotations__[_case.name].constructCase(*args)
key=_case,
value=get_case(cls.__annotations__[_case.name]).constructCase(*args),
)

if hasattr(cls, case.name):
Expand Down
44 changes: 44 additions & 0 deletions examples/sealed.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env python3

from adt import adt as sealed
from dataclasses import dataclass
from typing import Tuple


@sealed
class Sealed1:
EMPTY: None
INTEGER: int
STRING_PAIR: Tuple[str, str]


x1 = Sealed1.INTEGER(5)
print(x1.integer())
x2 = Sealed1.EMPTY()
print(x2.empty())
x3 = Sealed1.STRING_PAIR("foo", "bar")
print(x3.string_pair())


@dataclass
class Leaf:
data: int


@dataclass
class Node:
left: "Tree"
right: "Tree"


@sealed
class Tree:
EMPTY: None
LEAF: Leaf
NODE: Node


t1 = Tree.EMPTY()
t2 = Tree.LEAF(3)
t3 = Tree.NODE((Tree.LEAF(3), Tree.LEAF(4)))
print(t1, t2, t3)

0 comments on commit 1a700f1

Please sign in to comment.