morphir-python 0.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- morphir/__init__.py +14 -0
- morphir/ir/__init__.py +110 -0
- morphir/ir/access_controlled.py +15 -0
- morphir/ir/decorations.py +19 -0
- morphir/ir/diagnostics.py +105 -0
- morphir/ir/distribution.py +21 -0
- morphir/ir/document.py +37 -0
- morphir/ir/documented.py +11 -0
- morphir/ir/format_version.py +483 -0
- morphir/ir/fqname.py +9 -0
- morphir/ir/json.py +11 -0
- morphir/ir/literal.py +25 -0
- morphir/ir/meta.py +11 -0
- morphir/ir/migrate.py +1267 -0
- morphir/ir/module.py +17 -0
- morphir/ir/name.py +27 -0
- morphir/ir/package.py +15 -0
- morphir/ir/path.py +25 -0
- morphir/ir/qname.py +9 -0
- morphir/ir/ref.py +17 -0
- morphir/ir/type.py +37 -0
- morphir/ir/type_constraints.py +33 -0
- morphir/ir/type_def.py +19 -0
- morphir/ir/type_spec.py +25 -0
- morphir/ir/v3/__init__.py +64 -0
- morphir/ir/v3/_legacy_value.py +201 -0
- morphir/ir/v3/access_controlled.py +31 -0
- morphir/ir/v3/codec.py +1275 -0
- morphir/ir/v3/codec_v1.py +491 -0
- morphir/ir/v3/codec_v2.py +187 -0
- morphir/ir/v3/distribution.py +42 -0
- morphir/ir/v3/documented.py +13 -0
- morphir/ir/v3/fqname.py +30 -0
- morphir/ir/v3/literal.py +46 -0
- morphir/ir/v3/module.py +32 -0
- morphir/ir/v3/name.py +42 -0
- morphir/ir/v3/package.py +23 -0
- morphir/ir/v3/path.py +29 -0
- morphir/ir/v3/qname.py +16 -0
- morphir/ir/v3/type.py +126 -0
- morphir/ir/v3/value.py +235 -0
- morphir/ir/v4/__init__.py +160 -0
- morphir/ir/v4/access_controlled.py +17 -0
- morphir/ir/v4/annotation.py +75 -0
- morphir/ir/v4/codec.py +2161 -0
- morphir/ir/v4/decorations.py +88 -0
- morphir/ir/v4/distribution.py +56 -0
- morphir/ir/v4/document.py +69 -0
- morphir/ir/v4/documented.py +10 -0
- morphir/ir/v4/fqname.py +69 -0
- morphir/ir/v4/incompleteness.py +78 -0
- morphir/ir/v4/json.py +103 -0
- morphir/ir/v4/literal.py +51 -0
- morphir/ir/v4/meta.py +27 -0
- morphir/ir/v4/module.py +30 -0
- morphir/ir/v4/name.py +69 -0
- morphir/ir/v4/package.py +19 -0
- morphir/ir/v4/path.py +50 -0
- morphir/ir/v4/qname.py +34 -0
- morphir/ir/v4/ref.py +35 -0
- morphir/ir/v4/type.py +140 -0
- morphir/ir/v4/type_constraints.py +91 -0
- morphir/ir/v4/type_def.py +38 -0
- morphir/ir/v4/type_spec.py +64 -0
- morphir/ir/v4/value.py +480 -0
- morphir/ir/value.py +81 -0
- morphir/py.typed +0 -0
- morphir/sdk/__init__.py +110 -0
- morphir/sdk/_compare.py +187 -0
- morphir/sdk/aggregate.py +421 -0
- morphir/sdk/basics.py +504 -0
- morphir/sdk/char.py +110 -0
- morphir/sdk/decimal.py +311 -0
- morphir/sdk/dict.py +336 -0
- morphir/sdk/instant.py +118 -0
- morphir/sdk/int.py +86 -0
- morphir/sdk/key.py +522 -0
- morphir/sdk/list.py +356 -0
- morphir/sdk/local_date.py +436 -0
- morphir/sdk/local_time.py +267 -0
- morphir/sdk/maybe.py +135 -0
- morphir/sdk/number.py +237 -0
- morphir/sdk/regex.py +287 -0
- morphir/sdk/result.py +162 -0
- morphir/sdk/result_list.py +169 -0
- morphir/sdk/rule.py +103 -0
- morphir/sdk/set.py +214 -0
- morphir/sdk/stateful_app.py +49 -0
- morphir/sdk/string.py +427 -0
- morphir/sdk/tuple.py +43 -0
- morphir/sdk/uuid.py +209 -0
- morphir_python-0.0.1.dist-info/METADATA +269 -0
- morphir_python-0.0.1.dist-info/RECORD +99 -0
- morphir_python-0.0.1.dist-info/WHEEL +4 -0
- morphir_python-0.0.1.dist-info/entry_points.txt +2 -0
- morphir_python-0.0.1.dist-info/licenses/LICENSE +201 -0
- morphir_tools/__init__.py +13 -0
- morphir_tools/cli.py +223 -0
- morphir_tools/py.typed +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""V3 distributions (morphir-elm ``Morphir.IR.Distribution``).
|
|
2
|
+
|
|
3
|
+
Format 3.0.0 has only the ``Library`` distribution. Format 3.1.0 adds ``Specs``,
|
|
4
|
+
which publishes a package's specification without its definitions (finos/morphir
|
|
5
|
+
decision record 0018). Type attributes are unit (``None``) and value attributes
|
|
6
|
+
are the value's type. There is no package release version.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
|
|
11
|
+
from dataclasses import dataclass, field
|
|
12
|
+
|
|
13
|
+
from . import package
|
|
14
|
+
from .path import Path
|
|
15
|
+
from .type import Type
|
|
16
|
+
|
|
17
|
+
type TypedValueAttributes = Type[None]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class Library:
|
|
22
|
+
"""A format-3 library: a package name, dependencies, and a definition."""
|
|
23
|
+
|
|
24
|
+
package_name: Path
|
|
25
|
+
definition: package.Definition[None, Type[None]]
|
|
26
|
+
dependencies: dict[Path, package.Specification[None]] = field(default_factory=dict)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class Specs:
|
|
31
|
+
"""A format-3.1.0 Specs distribution: a package's public face.
|
|
32
|
+
|
|
33
|
+
It has the shape of a `Library`, with a package specification in place of the
|
|
34
|
+
package definition. Writers declare ``formatVersion`` ``"3.1.0"`` for it.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
package_name: Path
|
|
38
|
+
specification: package.Specification[None]
|
|
39
|
+
dependencies: dict[Path, package.Specification[None]] = field(default_factory=dict)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
type Distribution = Library | Specs
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""V3 documented values (morphir-elm ``Morphir.IR.Documented``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class Documented[T]:
|
|
10
|
+
"""A value with documentation. In v3 the documentation is always a string."""
|
|
11
|
+
|
|
12
|
+
doc: str
|
|
13
|
+
value: T
|
morphir/ir/v3/fqname.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"""V3 fully qualified names (morphir-elm ``Morphir.IR.FQName``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from . import name, path
|
|
8
|
+
from .name import Name
|
|
9
|
+
from .path import Path
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class FQName:
|
|
14
|
+
"""A package path, a module path, and a local name."""
|
|
15
|
+
|
|
16
|
+
package_path: Path
|
|
17
|
+
module_path: Path
|
|
18
|
+
local_name: Name
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def fqn(package: str, module: str, local: str) -> FQName:
|
|
22
|
+
"""Build an FQName from strings, as elm ``FQName.fqn`` does.
|
|
23
|
+
|
|
24
|
+
Example:
|
|
25
|
+
>>> fqn("Morphir.SDK", "Basics", "Int").local_name
|
|
26
|
+
('int',)
|
|
27
|
+
"""
|
|
28
|
+
return FQName(
|
|
29
|
+
path.from_string(package), path.from_string(module), name.from_string(local)
|
|
30
|
+
)
|
morphir/ir/v3/literal.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"""V3 literals (morphir-elm ``Morphir.IR.Literal``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from decimal import Decimal
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@dataclass(frozen=True)
|
|
10
|
+
class BoolLiteral:
|
|
11
|
+
value: bool
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class CharLiteral:
|
|
16
|
+
value: str
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class StringLiteral:
|
|
21
|
+
value: str
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class WholeNumberLiteral:
|
|
26
|
+
value: int
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class FloatLiteral:
|
|
31
|
+
value: float
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass(frozen=True)
|
|
35
|
+
class DecimalLiteral:
|
|
36
|
+
value: Decimal
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
type Literal = (
|
|
40
|
+
BoolLiteral
|
|
41
|
+
| CharLiteral
|
|
42
|
+
| StringLiteral
|
|
43
|
+
| WholeNumberLiteral
|
|
44
|
+
| FloatLiteral
|
|
45
|
+
| DecimalLiteral
|
|
46
|
+
)
|
morphir/ir/v3/module.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""V3 modules (morphir-elm ``Morphir.IR.Module``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
|
|
7
|
+
from . import type as t
|
|
8
|
+
from . import value as v
|
|
9
|
+
from .access_controlled import AccessControlled
|
|
10
|
+
from .documented import Documented
|
|
11
|
+
from .name import Name
|
|
12
|
+
from .path import Path
|
|
13
|
+
|
|
14
|
+
type ModuleName = Path
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class Specification[TA]:
|
|
19
|
+
types: dict[Name, Documented[t.Specification[TA]]] = field(default_factory=dict)
|
|
20
|
+
values: dict[Name, Documented[v.Specification[TA]]] = field(default_factory=dict)
|
|
21
|
+
doc: str | None = None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class Definition[TA, VA]:
|
|
26
|
+
types: dict[Name, AccessControlled[Documented[t.Definition[TA]]]] = field(
|
|
27
|
+
default_factory=dict
|
|
28
|
+
)
|
|
29
|
+
values: dict[Name, AccessControlled[Documented[v.Definition[TA, VA]]]] = field(
|
|
30
|
+
default_factory=dict
|
|
31
|
+
)
|
|
32
|
+
doc: str | None = None
|
morphir/ir/v3/name.py
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""V3 names: lists of lowercase words (morphir-elm ``Morphir.IR.Name``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Name(tuple[str, ...]):
|
|
9
|
+
"""A v3 name such as ``["value", "in", "u", "s", "d"]``.
|
|
10
|
+
|
|
11
|
+
Distinct from `morphir.ir.v4.Name` so that a type checker catches mixing.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
__slots__ = ()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def from_list(words: list[str] | tuple[str, ...]) -> Name:
|
|
18
|
+
"""Build a name from words, as elm ``Name.fromList`` does."""
|
|
19
|
+
return Name(tuple(words))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def to_list(name: Name) -> list[str]:
|
|
23
|
+
"""Return the words of a name."""
|
|
24
|
+
return list(name)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def from_string(text: str) -> Name:
|
|
28
|
+
"""Split text into lowercase words, as elm ``Name.fromString`` does.
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
>>> from_string("valueInUSD")
|
|
32
|
+
('value', 'in', 'u', 's', 'd')
|
|
33
|
+
"""
|
|
34
|
+
words = re.findall(r"[a-zA-Z][a-z]*|[0-9]+", text)
|
|
35
|
+
return Name(tuple(word.lower() for word in words))
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def to_camel_case(name: Name) -> str:
|
|
39
|
+
"""Render as camelCase, as elm ``Name.toCamelCase`` does."""
|
|
40
|
+
if not name:
|
|
41
|
+
return ""
|
|
42
|
+
return name[0] + "".join(word.capitalize() for word in name[1:])
|
morphir/ir/v3/package.py
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""V3 packages (morphir-elm ``Morphir.IR.Package``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass, field
|
|
6
|
+
|
|
7
|
+
from . import module
|
|
8
|
+
from .access_controlled import AccessControlled
|
|
9
|
+
from .path import Path
|
|
10
|
+
|
|
11
|
+
type PackageName = Path
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@dataclass(frozen=True)
|
|
15
|
+
class Specification[TA]:
|
|
16
|
+
modules: dict[Path, module.Specification[TA]] = field(default_factory=dict)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass(frozen=True)
|
|
20
|
+
class Definition[TA, VA]:
|
|
21
|
+
modules: dict[Path, AccessControlled[module.Definition[TA, VA]]] = field(
|
|
22
|
+
default_factory=dict
|
|
23
|
+
)
|
morphir/ir/v3/path.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"""V3 paths: lists of names (morphir-elm ``Morphir.IR.Path``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from .name import Name
|
|
6
|
+
from .name import from_string as name_from_string
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Path(tuple[Name, ...]):
|
|
10
|
+
"""A v3 path such as ``[["morphir"], ["s", "d", "k"]]``."""
|
|
11
|
+
|
|
12
|
+
__slots__ = ()
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def from_list(names: list[Name] | tuple[Name, ...]) -> Path:
|
|
16
|
+
"""Build a path from names."""
|
|
17
|
+
return Path(tuple(names))
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def to_list(path: Path) -> list[Name]:
|
|
21
|
+
"""Return the names of a path."""
|
|
22
|
+
return list(path)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def from_string(text: str) -> Path:
|
|
26
|
+
"""Split ``Morphir.SDK`` or ``morphir/sdk`` into a path of names."""
|
|
27
|
+
import re
|
|
28
|
+
|
|
29
|
+
return Path(tuple(name_from_string(p) for p in re.split(r"[./]", text) if p))
|
morphir/ir/v3/qname.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"""V3 qualified names (morphir-elm ``Morphir.IR.QName``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
from .name import Name
|
|
8
|
+
from .path import Path
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class QName:
|
|
13
|
+
"""A module path and a local name."""
|
|
14
|
+
|
|
15
|
+
module_path: Path
|
|
16
|
+
local_name: Name
|
morphir/ir/v3/type.py
ADDED
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"""V3 types (morphir-elm ``Morphir.IR.Type``).
|
|
2
|
+
|
|
3
|
+
Every node is parameterized by its attribute type ``A``. A distribution fixes
|
|
4
|
+
``A`` to ``None``, which is elm's unit ``()``.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from dataclasses import dataclass
|
|
10
|
+
|
|
11
|
+
from .access_controlled import AccessControlled
|
|
12
|
+
from .fqname import FQName
|
|
13
|
+
from .name import Name
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class Variable[A]:
|
|
18
|
+
attributes: A
|
|
19
|
+
name: Name
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class Reference[A]:
|
|
24
|
+
attributes: A
|
|
25
|
+
fqname: FQName
|
|
26
|
+
args: tuple[Type[A], ...] = ()
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@dataclass(frozen=True)
|
|
30
|
+
class Tuple[A]:
|
|
31
|
+
attributes: A
|
|
32
|
+
elements: tuple[Type[A], ...] = ()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@dataclass(frozen=True)
|
|
36
|
+
class Record[A]:
|
|
37
|
+
attributes: A
|
|
38
|
+
fields: tuple[Field[A], ...] = ()
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True)
|
|
42
|
+
class ExtensibleRecord[A]:
|
|
43
|
+
attributes: A
|
|
44
|
+
variable: Name
|
|
45
|
+
fields: tuple[Field[A], ...] = ()
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class Function[A]:
|
|
50
|
+
attributes: A
|
|
51
|
+
argument_type: Type[A]
|
|
52
|
+
return_type: Type[A]
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True)
|
|
56
|
+
class Unit[A]:
|
|
57
|
+
attributes: A
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
type Type[A] = (
|
|
61
|
+
Variable[A]
|
|
62
|
+
| Reference[A]
|
|
63
|
+
| Tuple[A]
|
|
64
|
+
| Record[A]
|
|
65
|
+
| ExtensibleRecord[A]
|
|
66
|
+
| Function[A]
|
|
67
|
+
| Unit[A]
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class Field[A]:
|
|
73
|
+
name: Name
|
|
74
|
+
tpe: Type[A]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
type ConstructorArgs[A] = tuple[tuple[Name, Type[A]], ...]
|
|
78
|
+
type Constructors[A] = dict[Name, ConstructorArgs[A]]
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(frozen=True)
|
|
82
|
+
class TypeAliasSpecification[A]:
|
|
83
|
+
type_params: tuple[Name, ...]
|
|
84
|
+
tpe: Type[A]
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@dataclass(frozen=True)
|
|
88
|
+
class OpaqueTypeSpecification:
|
|
89
|
+
type_params: tuple[Name, ...]
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
@dataclass(frozen=True)
|
|
93
|
+
class CustomTypeSpecification[A]:
|
|
94
|
+
type_params: tuple[Name, ...]
|
|
95
|
+
constructors: Constructors[A]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass(frozen=True)
|
|
99
|
+
class DerivedTypeSpecification[A]:
|
|
100
|
+
type_params: tuple[Name, ...]
|
|
101
|
+
base_type: Type[A]
|
|
102
|
+
from_base_type: FQName
|
|
103
|
+
to_base_type: FQName
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
type Specification[A] = (
|
|
107
|
+
TypeAliasSpecification[A]
|
|
108
|
+
| OpaqueTypeSpecification
|
|
109
|
+
| CustomTypeSpecification[A]
|
|
110
|
+
| DerivedTypeSpecification[A]
|
|
111
|
+
)
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass(frozen=True)
|
|
115
|
+
class TypeAliasDefinition[A]:
|
|
116
|
+
type_params: tuple[Name, ...]
|
|
117
|
+
tpe: Type[A]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
@dataclass(frozen=True)
|
|
121
|
+
class CustomTypeDefinition[A]:
|
|
122
|
+
type_params: tuple[Name, ...]
|
|
123
|
+
constructors: AccessControlled[Constructors[A]]
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
type Definition[A] = TypeAliasDefinition[A] | CustomTypeDefinition[A]
|
morphir/ir/v3/value.py
ADDED
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""V3 values and patterns (morphir-elm ``Morphir.IR.Value``).
|
|
2
|
+
|
|
3
|
+
Values take two attribute parameters, as in elm: ``TA`` for the types inside
|
|
4
|
+
definitions and ``VA`` for value and pattern nodes. A distribution fixes ``TA`` to
|
|
5
|
+
``None`` and ``VA`` to ``Type[None]``.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass
|
|
11
|
+
|
|
12
|
+
from .fqname import FQName
|
|
13
|
+
from .literal import Literal
|
|
14
|
+
from .name import Name
|
|
15
|
+
from .type import Type
|
|
16
|
+
|
|
17
|
+
# --- Patterns ---
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class WildcardPattern[A]:
|
|
22
|
+
attributes: A
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True)
|
|
26
|
+
class AsPattern[A]:
|
|
27
|
+
attributes: A
|
|
28
|
+
pattern: Pattern[A]
|
|
29
|
+
name: Name
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class TuplePattern[A]:
|
|
34
|
+
attributes: A
|
|
35
|
+
elements: tuple[Pattern[A], ...]
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class ConstructorPattern[A]:
|
|
40
|
+
attributes: A
|
|
41
|
+
constructor: FQName
|
|
42
|
+
args: tuple[Pattern[A], ...]
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class EmptyListPattern[A]:
|
|
47
|
+
attributes: A
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class HeadTailPattern[A]:
|
|
52
|
+
attributes: A
|
|
53
|
+
head: Pattern[A]
|
|
54
|
+
tail: Pattern[A]
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class LiteralPattern[A]:
|
|
59
|
+
attributes: A
|
|
60
|
+
literal: Literal
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@dataclass(frozen=True)
|
|
64
|
+
class UnitPattern[A]:
|
|
65
|
+
attributes: A
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
type Pattern[A] = (
|
|
69
|
+
WildcardPattern[A]
|
|
70
|
+
| AsPattern[A]
|
|
71
|
+
| TuplePattern[A]
|
|
72
|
+
| ConstructorPattern[A]
|
|
73
|
+
| EmptyListPattern[A]
|
|
74
|
+
| HeadTailPattern[A]
|
|
75
|
+
| LiteralPattern[A]
|
|
76
|
+
| UnitPattern[A]
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# --- Values ---
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
@dataclass(frozen=True)
|
|
83
|
+
class LiteralValue[TA, VA]:
|
|
84
|
+
attributes: VA
|
|
85
|
+
literal: Literal
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@dataclass(frozen=True)
|
|
89
|
+
class Constructor[TA, VA]:
|
|
90
|
+
attributes: VA
|
|
91
|
+
fqname: FQName
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@dataclass(frozen=True)
|
|
95
|
+
class Tuple[TA, VA]:
|
|
96
|
+
attributes: VA
|
|
97
|
+
elements: tuple[Value[TA, VA], ...]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
@dataclass(frozen=True)
|
|
101
|
+
class List[TA, VA]:
|
|
102
|
+
attributes: VA
|
|
103
|
+
items: tuple[Value[TA, VA], ...]
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@dataclass(frozen=True)
|
|
107
|
+
class Record[TA, VA]:
|
|
108
|
+
attributes: VA
|
|
109
|
+
fields: dict[Name, Value[TA, VA]]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
@dataclass(frozen=True)
|
|
113
|
+
class Variable[TA, VA]:
|
|
114
|
+
attributes: VA
|
|
115
|
+
name: Name
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@dataclass(frozen=True)
|
|
119
|
+
class Reference[TA, VA]:
|
|
120
|
+
attributes: VA
|
|
121
|
+
fqname: FQName
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
@dataclass(frozen=True)
|
|
125
|
+
class Field[TA, VA]:
|
|
126
|
+
attributes: VA
|
|
127
|
+
subject: Value[TA, VA]
|
|
128
|
+
field_name: Name
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
@dataclass(frozen=True)
|
|
132
|
+
class FieldFunction[TA, VA]:
|
|
133
|
+
attributes: VA
|
|
134
|
+
name: Name
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@dataclass(frozen=True)
|
|
138
|
+
class Apply[TA, VA]:
|
|
139
|
+
attributes: VA
|
|
140
|
+
function: Value[TA, VA]
|
|
141
|
+
argument: Value[TA, VA]
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
@dataclass(frozen=True)
|
|
145
|
+
class Lambda[TA, VA]:
|
|
146
|
+
attributes: VA
|
|
147
|
+
pattern: Pattern[VA]
|
|
148
|
+
body: Value[TA, VA]
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
@dataclass(frozen=True)
|
|
152
|
+
class LetDefinition[TA, VA]:
|
|
153
|
+
attributes: VA
|
|
154
|
+
name: Name
|
|
155
|
+
definition: Definition[TA, VA]
|
|
156
|
+
in_value: Value[TA, VA]
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@dataclass(frozen=True)
|
|
160
|
+
class LetRecursion[TA, VA]:
|
|
161
|
+
attributes: VA
|
|
162
|
+
definitions: dict[Name, Definition[TA, VA]]
|
|
163
|
+
in_value: Value[TA, VA]
|
|
164
|
+
|
|
165
|
+
|
|
166
|
+
@dataclass(frozen=True)
|
|
167
|
+
class Destructure[TA, VA]:
|
|
168
|
+
attributes: VA
|
|
169
|
+
pattern: Pattern[VA]
|
|
170
|
+
value_to_destructure: Value[TA, VA]
|
|
171
|
+
in_value: Value[TA, VA]
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
@dataclass(frozen=True)
|
|
175
|
+
class IfThenElse[TA, VA]:
|
|
176
|
+
attributes: VA
|
|
177
|
+
condition: Value[TA, VA]
|
|
178
|
+
then_branch: Value[TA, VA]
|
|
179
|
+
else_branch: Value[TA, VA]
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
@dataclass(frozen=True)
|
|
183
|
+
class PatternMatch[TA, VA]:
|
|
184
|
+
attributes: VA
|
|
185
|
+
branch_on: Value[TA, VA]
|
|
186
|
+
cases: tuple[tuple[Pattern[VA], Value[TA, VA]], ...]
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
@dataclass(frozen=True)
|
|
190
|
+
class UpdateRecord[TA, VA]:
|
|
191
|
+
attributes: VA
|
|
192
|
+
value_to_update: Value[TA, VA]
|
|
193
|
+
fields: dict[Name, Value[TA, VA]]
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
@dataclass(frozen=True)
|
|
197
|
+
class Unit[TA, VA]:
|
|
198
|
+
attributes: VA
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
type Value[TA, VA] = (
|
|
202
|
+
LiteralValue[TA, VA]
|
|
203
|
+
| Constructor[TA, VA]
|
|
204
|
+
| Tuple[TA, VA]
|
|
205
|
+
| List[TA, VA]
|
|
206
|
+
| Record[TA, VA]
|
|
207
|
+
| Variable[TA, VA]
|
|
208
|
+
| Reference[TA, VA]
|
|
209
|
+
| Field[TA, VA]
|
|
210
|
+
| FieldFunction[TA, VA]
|
|
211
|
+
| Apply[TA, VA]
|
|
212
|
+
| Lambda[TA, VA]
|
|
213
|
+
| LetDefinition[TA, VA]
|
|
214
|
+
| LetRecursion[TA, VA]
|
|
215
|
+
| Destructure[TA, VA]
|
|
216
|
+
| IfThenElse[TA, VA]
|
|
217
|
+
| PatternMatch[TA, VA]
|
|
218
|
+
| UpdateRecord[TA, VA]
|
|
219
|
+
| Unit[TA, VA]
|
|
220
|
+
)
|
|
221
|
+
|
|
222
|
+
# --- Specifications and definitions ---
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@dataclass(frozen=True)
|
|
226
|
+
class Specification[TA]:
|
|
227
|
+
inputs: tuple[tuple[Name, Type[TA]], ...]
|
|
228
|
+
output: Type[TA]
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
@dataclass(frozen=True)
|
|
232
|
+
class Definition[TA, VA]:
|
|
233
|
+
input_types: tuple[tuple[Name, VA, Type[TA]], ...]
|
|
234
|
+
output_type: Type[TA]
|
|
235
|
+
body: Value[TA, VA]
|