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
morphir/ir/v4/path.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from .name import Name
|
|
2
|
+
from .name import from_string as name_from_string
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Path(tuple[Name, ...]):
|
|
6
|
+
pass
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def from_list(names: list[Name]) -> Path:
|
|
10
|
+
return Path(tuple(names))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def to_list(path: Path) -> list[Name]:
|
|
14
|
+
return list(path)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def from_string(s: str) -> Path:
|
|
18
|
+
if not s:
|
|
19
|
+
return Path(tuple())
|
|
20
|
+
# Support both "/" (v4) and "." (legacy) as separators
|
|
21
|
+
# Use regex split to handle both
|
|
22
|
+
import re
|
|
23
|
+
|
|
24
|
+
parts = re.split(r"[/\.]", s)
|
|
25
|
+
return Path(tuple(name_from_string(p) for p in parts if p))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def to_string(path: Path, separator: str = "/") -> str:
|
|
29
|
+
# Default separator per IR v4 is "/"
|
|
30
|
+
from .name import to_kebab_case
|
|
31
|
+
|
|
32
|
+
return separator.join(to_kebab_case(name) for name in path)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def empty() -> Path:
|
|
36
|
+
return Path(tuple())
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def append(path: Path, name: Name) -> Path:
|
|
40
|
+
return Path(path + (name,))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def concat(path1: Path, path2: Path) -> Path:
|
|
44
|
+
return Path(path1 + path2)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def is_prefix_of(prefix: Path, path: Path) -> bool:
|
|
48
|
+
if len(prefix) > len(path):
|
|
49
|
+
return False
|
|
50
|
+
return path[: len(prefix)] == prefix
|
morphir/ir/v4/qname.py
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
|
|
3
|
+
from . import name, path
|
|
4
|
+
from .name import Name
|
|
5
|
+
from .path import Path
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
@dataclass(frozen=True)
|
|
9
|
+
class QName:
|
|
10
|
+
module_path: Path
|
|
11
|
+
local_name: Name
|
|
12
|
+
|
|
13
|
+
@staticmethod
|
|
14
|
+
def from_tuple(t: tuple[Path, Name]) -> QName:
|
|
15
|
+
return QName(t[0], t[1])
|
|
16
|
+
|
|
17
|
+
def to_tuple(self) -> tuple[Path, Name]:
|
|
18
|
+
return (self.module_path, self.local_name)
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def from_name(n: Name) -> QName:
|
|
22
|
+
return QName(path.empty(), n)
|
|
23
|
+
|
|
24
|
+
def to_string(self) -> str:
|
|
25
|
+
module_str = path.to_string(self.module_path, ".")
|
|
26
|
+
local_str = name.to_camel_case(self.local_name)
|
|
27
|
+
return f"{module_str}:{local_str}"
|
|
28
|
+
|
|
29
|
+
@staticmethod
|
|
30
|
+
def from_string(s: str) -> QName:
|
|
31
|
+
parts = s.split(":")
|
|
32
|
+
if len(parts) == 2:
|
|
33
|
+
return QName(path.from_string(parts[0]), name.from_string(parts[1]))
|
|
34
|
+
return QName(path.empty(), name.from_string(s))
|
morphir/ir/v4/ref.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from typing import Any, Generic, TypeVar, Union
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
@dataclass(frozen=True)
|
|
6
|
+
class DefRef:
|
|
7
|
+
"""Shorthand reference to an entry in $defs."""
|
|
8
|
+
|
|
9
|
+
name: str
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class PointerRef:
|
|
14
|
+
"""Full JSON Pointer reference."""
|
|
15
|
+
|
|
16
|
+
pointer: list[str]
|
|
17
|
+
|
|
18
|
+
@staticmethod
|
|
19
|
+
def from_string(pointer_str: str) -> PointerRef:
|
|
20
|
+
if pointer_str.startswith("#/"):
|
|
21
|
+
# Remove #/ and split
|
|
22
|
+
path = pointer_str[2:].split("/")
|
|
23
|
+
return PointerRef(pointer=path)
|
|
24
|
+
raise ValueError(f"Invalid pointer string: {pointer_str}")
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Ref = Union[DefRef, PointerRef]
|
|
28
|
+
|
|
29
|
+
T = TypeVar("T")
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class FileWithDefs(Generic[T]):
|
|
34
|
+
content: T
|
|
35
|
+
defs: dict[str, Any] = field(default_factory=dict)
|
morphir/ir/v4/type.py
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Any
|
|
5
|
+
from typing import Union as TUnion
|
|
6
|
+
|
|
7
|
+
from .fqname import FQName
|
|
8
|
+
from .name import Name
|
|
9
|
+
from .type_constraints import TypeConstraints
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class SourceLocation:
|
|
14
|
+
start_line: int
|
|
15
|
+
start_column: int
|
|
16
|
+
end_line: int
|
|
17
|
+
end_column: int
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@dataclass(frozen=True)
|
|
21
|
+
class TypeAttributes:
|
|
22
|
+
source: SourceLocation | None = None
|
|
23
|
+
constraints: TypeConstraints | None = None
|
|
24
|
+
extensions: dict[FQName, Any] = field(
|
|
25
|
+
default_factory=dict
|
|
26
|
+
) # Any for extensions due to circular dep with Value
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
EMPTY_TYPE_ATTRIBUTES = TypeAttributes()
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class Variable:
|
|
34
|
+
attributes: TypeAttributes
|
|
35
|
+
name: Name
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@dataclass(frozen=True)
|
|
39
|
+
class Reference:
|
|
40
|
+
attributes: TypeAttributes
|
|
41
|
+
fqname: FQName
|
|
42
|
+
args: list[Type] = field(default_factory=list)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@dataclass(frozen=True)
|
|
46
|
+
class Tuple:
|
|
47
|
+
attributes: TypeAttributes
|
|
48
|
+
elements: list[Type] = field(default_factory=list)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True)
|
|
52
|
+
class Record:
|
|
53
|
+
attributes: TypeAttributes
|
|
54
|
+
fields: list[Field] = field(default_factory=list)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
@dataclass(frozen=True)
|
|
58
|
+
class ExtensibleRecord:
|
|
59
|
+
attributes: TypeAttributes
|
|
60
|
+
variable: Name
|
|
61
|
+
fields: list[Field] = field(default_factory=list)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class Function:
|
|
66
|
+
attributes: TypeAttributes
|
|
67
|
+
argument_type: Type
|
|
68
|
+
return_type: Type
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
@dataclass(frozen=True)
|
|
72
|
+
class Unit:
|
|
73
|
+
attributes: TypeAttributes
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@dataclass(frozen=True)
|
|
77
|
+
class Union:
|
|
78
|
+
"""An untagged union: values of at least one of the alternative types.
|
|
79
|
+
|
|
80
|
+
Draft v4 type expression (finos/morphir ``docs/spec/draft/types.md``). It
|
|
81
|
+
introduces no constructor or tag. Alternative order, duplicates and nesting
|
|
82
|
+
are content and are kept.
|
|
83
|
+
|
|
84
|
+
Attributes:
|
|
85
|
+
attributes: The type attributes.
|
|
86
|
+
alternatives: Two or more alternative types.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
attributes: TypeAttributes
|
|
90
|
+
alternatives: list[Type] = field(default_factory=list)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Type = TUnion[
|
|
94
|
+
Variable, Reference, Tuple, Record, ExtensibleRecord, Function, Unit, Union
|
|
95
|
+
]
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
@dataclass(frozen=True)
|
|
99
|
+
class Field:
|
|
100
|
+
name: Name
|
|
101
|
+
tpe: Type
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def get_attributes(tpe: Type) -> TypeAttributes:
|
|
105
|
+
return tpe.attributes
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def map_attributes(tpe: Type, f: Any) -> Type:
|
|
109
|
+
# f should be Callable[[TypeAttributes], TypeAttributes]
|
|
110
|
+
# But doing precise typing here might be verbose with Union destructuring
|
|
111
|
+
# For now, simplistic implementation
|
|
112
|
+
ta = tpe.attributes
|
|
113
|
+
new_ta = f(ta)
|
|
114
|
+
|
|
115
|
+
if isinstance(tpe, Variable):
|
|
116
|
+
return Variable(new_ta, tpe.name)
|
|
117
|
+
elif isinstance(tpe, Reference):
|
|
118
|
+
return Reference(new_ta, tpe.fqname, [map_attributes(a, f) for a in tpe.args])
|
|
119
|
+
elif isinstance(tpe, Tuple):
|
|
120
|
+
return Tuple(new_ta, [map_attributes(e, f) for e in tpe.elements])
|
|
121
|
+
elif isinstance(tpe, Record):
|
|
122
|
+
return Record(
|
|
123
|
+
new_ta, [Field(fl.name, map_attributes(fl.tpe, f)) for fl in tpe.fields]
|
|
124
|
+
)
|
|
125
|
+
elif isinstance(tpe, ExtensibleRecord):
|
|
126
|
+
return ExtensibleRecord(
|
|
127
|
+
new_ta,
|
|
128
|
+
tpe.variable,
|
|
129
|
+
[Field(fl.name, map_attributes(fl.tpe, f)) for fl in tpe.fields],
|
|
130
|
+
)
|
|
131
|
+
elif isinstance(tpe, Function):
|
|
132
|
+
return Function(
|
|
133
|
+
new_ta,
|
|
134
|
+
map_attributes(tpe.argument_type, f),
|
|
135
|
+
map_attributes(tpe.return_type, f),
|
|
136
|
+
)
|
|
137
|
+
elif isinstance(tpe, Union):
|
|
138
|
+
return Union(new_ta, [map_attributes(a, f) for a in tpe.alternatives])
|
|
139
|
+
else:
|
|
140
|
+
return Unit(new_ta)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from enum import Enum, auto
|
|
3
|
+
from typing import Literal, Union
|
|
4
|
+
|
|
5
|
+
from .fqname import FQName
|
|
6
|
+
|
|
7
|
+
# Numeric Constraints
|
|
8
|
+
IntWidth = Literal[8, 16, 32, 64]
|
|
9
|
+
FloatWidth = Literal[32, 64]
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@dataclass(frozen=True)
|
|
13
|
+
class Signed:
|
|
14
|
+
bits: IntWidth
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class Unsigned:
|
|
19
|
+
bits: IntWidth
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass(frozen=True)
|
|
23
|
+
class FloatingPoint:
|
|
24
|
+
bits: FloatWidth
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class Bounded:
|
|
29
|
+
min: int | None = None
|
|
30
|
+
max: int | None = None
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class Decimal:
|
|
35
|
+
precision: int
|
|
36
|
+
scale: int
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
NumericConstraint = Union[Signed, Unsigned, FloatingPoint, Bounded, Decimal]
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# String Constraints
|
|
43
|
+
class StringEncoding(Enum):
|
|
44
|
+
UTF8 = auto()
|
|
45
|
+
UTF16 = auto()
|
|
46
|
+
ASCII = auto()
|
|
47
|
+
LATIN1 = auto()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class StringConstraint:
|
|
52
|
+
encoding: StringEncoding | None = None
|
|
53
|
+
min_length: int | None = None
|
|
54
|
+
max_length: int | None = None
|
|
55
|
+
pattern: str | None = None
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
# Collection Constraints
|
|
59
|
+
@dataclass(frozen=True)
|
|
60
|
+
class CollectionConstraint:
|
|
61
|
+
min_length: int | None = None
|
|
62
|
+
max_length: int | None = None
|
|
63
|
+
unique_items: bool = False
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Custom Constraints
|
|
67
|
+
# We use 'Any' for arguments to avoid circular dependency with Value for now
|
|
68
|
+
# Ideally this should be Value, but Value depends on Type (sometimes)
|
|
69
|
+
from typing import Any
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class CustomConstraint:
|
|
74
|
+
predicate: FQName
|
|
75
|
+
arguments: list[Any]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True)
|
|
79
|
+
class TypeConstraints:
|
|
80
|
+
"""Structured constraints on a type.
|
|
81
|
+
|
|
82
|
+
Deprecated: the upstream v4 schema keeps ``TypeAttributes.constraints`` as a
|
|
83
|
+
placeholder with no defined members, so these constraints have no v4 spelling
|
|
84
|
+
and encoding fails with ``no_v4_spelling``. Keep constraints in
|
|
85
|
+
``TypeAttributes.extensions`` until upstream defines them.
|
|
86
|
+
"""
|
|
87
|
+
|
|
88
|
+
numeric: NumericConstraint | None = None
|
|
89
|
+
string: StringConstraint | None = None
|
|
90
|
+
collection: CollectionConstraint | None = None
|
|
91
|
+
custom: list[CustomConstraint] = field(default_factory=list)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import Union
|
|
3
|
+
|
|
4
|
+
from .access_controlled import AccessControlled
|
|
5
|
+
from .incompleteness import Incompleteness
|
|
6
|
+
from .name import Name
|
|
7
|
+
from .type import Type
|
|
8
|
+
from .type_spec import Constructors
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class TypeAliasDefinition:
|
|
13
|
+
type_params: list[Name]
|
|
14
|
+
tpe: Type
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@dataclass(frozen=True)
|
|
18
|
+
class CustomTypeDefinition:
|
|
19
|
+
type_params: list[Name]
|
|
20
|
+
constructors: AccessControlled[Constructors]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class IncompleteTypeDefinition:
|
|
25
|
+
"""A type definition that is not complete yet.
|
|
26
|
+
|
|
27
|
+
Attributes:
|
|
28
|
+
type_params: The declared type parameters.
|
|
29
|
+
incompleteness: Why the definition is incomplete.
|
|
30
|
+
partial_type_exp: The type expression written so far, if any.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
type_params: list[Name]
|
|
34
|
+
incompleteness: Incompleteness
|
|
35
|
+
partial_type_exp: Type | None = None
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
Definition = Union[TypeAliasDefinition, CustomTypeDefinition, IncompleteTypeDefinition]
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import Union
|
|
5
|
+
|
|
6
|
+
from .annotation import Annotation
|
|
7
|
+
from .fqname import FQName
|
|
8
|
+
from .name import Name
|
|
9
|
+
from .type import Type
|
|
10
|
+
|
|
11
|
+
ConstructorArgs = list[tuple[Name, Type]]
|
|
12
|
+
Constructors = dict[Name, ConstructorArgs]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass(frozen=True)
|
|
16
|
+
class TypeAliasSpecification:
|
|
17
|
+
"""Specification for a type alias."""
|
|
18
|
+
|
|
19
|
+
type_params: list[Name]
|
|
20
|
+
tpe: Type
|
|
21
|
+
annotations: list[Annotation] = field(default_factory=list)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@dataclass(frozen=True)
|
|
25
|
+
class OpaqueTypeSpecification:
|
|
26
|
+
"""Specification for an opaque type."""
|
|
27
|
+
|
|
28
|
+
type_params: list[Name]
|
|
29
|
+
annotations: list[Annotation] = field(default_factory=list)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class CustomTypeSpecification:
|
|
34
|
+
"""Specification for a custom type (ADT)."""
|
|
35
|
+
|
|
36
|
+
type_params: list[Name]
|
|
37
|
+
constructors: Constructors
|
|
38
|
+
annotations: list[Annotation] = field(default_factory=list)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
@dataclass(frozen=True)
|
|
42
|
+
class DerivedTypeSpecificationDetails:
|
|
43
|
+
"""Details for a derived type."""
|
|
44
|
+
|
|
45
|
+
base_type: Type
|
|
46
|
+
from_base_type: FQName
|
|
47
|
+
to_base_type: FQName
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@dataclass(frozen=True)
|
|
51
|
+
class DerivedTypeSpecification:
|
|
52
|
+
"""Specification for a derived type."""
|
|
53
|
+
|
|
54
|
+
type_params: list[Name]
|
|
55
|
+
details: DerivedTypeSpecificationDetails
|
|
56
|
+
annotations: list[Annotation] = field(default_factory=list)
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
Specification = Union[
|
|
60
|
+
TypeAliasSpecification,
|
|
61
|
+
OpaqueTypeSpecification,
|
|
62
|
+
CustomTypeSpecification,
|
|
63
|
+
DerivedTypeSpecification,
|
|
64
|
+
]
|