guppylang-internals 0.21.0__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.
- guppylang_internals/__init__.py +3 -0
- guppylang_internals/ast_util.py +350 -0
- guppylang_internals/cfg/__init__.py +0 -0
- guppylang_internals/cfg/analysis.py +230 -0
- guppylang_internals/cfg/bb.py +221 -0
- guppylang_internals/cfg/builder.py +606 -0
- guppylang_internals/cfg/cfg.py +117 -0
- guppylang_internals/checker/__init__.py +0 -0
- guppylang_internals/checker/cfg_checker.py +388 -0
- guppylang_internals/checker/core.py +550 -0
- guppylang_internals/checker/errors/__init__.py +0 -0
- guppylang_internals/checker/errors/comptime_errors.py +106 -0
- guppylang_internals/checker/errors/generic.py +45 -0
- guppylang_internals/checker/errors/linearity.py +300 -0
- guppylang_internals/checker/errors/type_errors.py +344 -0
- guppylang_internals/checker/errors/wasm.py +34 -0
- guppylang_internals/checker/expr_checker.py +1413 -0
- guppylang_internals/checker/func_checker.py +269 -0
- guppylang_internals/checker/linearity_checker.py +821 -0
- guppylang_internals/checker/stmt_checker.py +447 -0
- guppylang_internals/compiler/__init__.py +0 -0
- guppylang_internals/compiler/cfg_compiler.py +233 -0
- guppylang_internals/compiler/core.py +613 -0
- guppylang_internals/compiler/expr_compiler.py +989 -0
- guppylang_internals/compiler/func_compiler.py +97 -0
- guppylang_internals/compiler/hugr_extension.py +224 -0
- guppylang_internals/compiler/qtm_platform_extension.py +0 -0
- guppylang_internals/compiler/stmt_compiler.py +212 -0
- guppylang_internals/decorator.py +246 -0
- guppylang_internals/definition/__init__.py +0 -0
- guppylang_internals/definition/common.py +214 -0
- guppylang_internals/definition/const.py +74 -0
- guppylang_internals/definition/custom.py +492 -0
- guppylang_internals/definition/declaration.py +171 -0
- guppylang_internals/definition/extern.py +89 -0
- guppylang_internals/definition/function.py +302 -0
- guppylang_internals/definition/overloaded.py +150 -0
- guppylang_internals/definition/parameter.py +82 -0
- guppylang_internals/definition/pytket_circuits.py +405 -0
- guppylang_internals/definition/struct.py +392 -0
- guppylang_internals/definition/traced.py +151 -0
- guppylang_internals/definition/ty.py +51 -0
- guppylang_internals/definition/value.py +115 -0
- guppylang_internals/definition/wasm.py +61 -0
- guppylang_internals/diagnostic.py +523 -0
- guppylang_internals/dummy_decorator.py +76 -0
- guppylang_internals/engine.py +295 -0
- guppylang_internals/error.py +107 -0
- guppylang_internals/experimental.py +92 -0
- guppylang_internals/ipython_inspect.py +28 -0
- guppylang_internals/nodes.py +427 -0
- guppylang_internals/py.typed +0 -0
- guppylang_internals/span.py +150 -0
- guppylang_internals/std/__init__.py +0 -0
- guppylang_internals/std/_internal/__init__.py +0 -0
- guppylang_internals/std/_internal/checker.py +573 -0
- guppylang_internals/std/_internal/compiler/__init__.py +0 -0
- guppylang_internals/std/_internal/compiler/arithmetic.py +136 -0
- guppylang_internals/std/_internal/compiler/array.py +569 -0
- guppylang_internals/std/_internal/compiler/either.py +131 -0
- guppylang_internals/std/_internal/compiler/frozenarray.py +68 -0
- guppylang_internals/std/_internal/compiler/futures.py +30 -0
- guppylang_internals/std/_internal/compiler/list.py +348 -0
- guppylang_internals/std/_internal/compiler/mem.py +13 -0
- guppylang_internals/std/_internal/compiler/option.py +78 -0
- guppylang_internals/std/_internal/compiler/prelude.py +271 -0
- guppylang_internals/std/_internal/compiler/qsystem.py +48 -0
- guppylang_internals/std/_internal/compiler/quantum.py +118 -0
- guppylang_internals/std/_internal/compiler/tket_bool.py +55 -0
- guppylang_internals/std/_internal/compiler/tket_exts.py +59 -0
- guppylang_internals/std/_internal/compiler/wasm.py +135 -0
- guppylang_internals/std/_internal/compiler.py +0 -0
- guppylang_internals/std/_internal/debug.py +95 -0
- guppylang_internals/std/_internal/util.py +271 -0
- guppylang_internals/tracing/__init__.py +0 -0
- guppylang_internals/tracing/builtins_mock.py +62 -0
- guppylang_internals/tracing/frozenlist.py +57 -0
- guppylang_internals/tracing/function.py +186 -0
- guppylang_internals/tracing/object.py +551 -0
- guppylang_internals/tracing/state.py +69 -0
- guppylang_internals/tracing/unpacking.py +194 -0
- guppylang_internals/tracing/util.py +86 -0
- guppylang_internals/tys/__init__.py +0 -0
- guppylang_internals/tys/arg.py +115 -0
- guppylang_internals/tys/builtin.py +382 -0
- guppylang_internals/tys/common.py +110 -0
- guppylang_internals/tys/const.py +114 -0
- guppylang_internals/tys/errors.py +178 -0
- guppylang_internals/tys/param.py +251 -0
- guppylang_internals/tys/parsing.py +425 -0
- guppylang_internals/tys/printing.py +174 -0
- guppylang_internals/tys/subst.py +112 -0
- guppylang_internals/tys/ty.py +876 -0
- guppylang_internals/tys/var.py +49 -0
- guppylang_internals-0.21.0.dist-info/METADATA +253 -0
- guppylang_internals-0.21.0.dist-info/RECORD +98 -0
- guppylang_internals-0.21.0.dist-info/WHEEL +4 -0
- guppylang_internals-0.21.0.dist-info/licenses/LICENCE +201 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
import builtins
|
|
2
|
+
import inspect
|
|
3
|
+
from collections.abc import Callable, Sequence
|
|
4
|
+
from types import FrameType
|
|
5
|
+
from typing import ParamSpec, TypeVar
|
|
6
|
+
|
|
7
|
+
from hugr import ops
|
|
8
|
+
from hugr import tys as ht
|
|
9
|
+
|
|
10
|
+
from guppylang.defs import (
|
|
11
|
+
GuppyDefinition,
|
|
12
|
+
GuppyFunctionDefinition,
|
|
13
|
+
)
|
|
14
|
+
from guppylang_internals.compiler.core import (
|
|
15
|
+
CompilerContext,
|
|
16
|
+
GlobalConstId,
|
|
17
|
+
)
|
|
18
|
+
from guppylang_internals.definition.common import DefId
|
|
19
|
+
from guppylang_internals.definition.custom import (
|
|
20
|
+
CustomCallChecker,
|
|
21
|
+
CustomFunctionDef,
|
|
22
|
+
CustomInoutCallCompiler,
|
|
23
|
+
DefaultCallChecker,
|
|
24
|
+
NotImplementedCallCompiler,
|
|
25
|
+
OpCompiler,
|
|
26
|
+
RawCustomFunctionDef,
|
|
27
|
+
)
|
|
28
|
+
from guppylang_internals.definition.ty import OpaqueTypeDef, TypeDef
|
|
29
|
+
from guppylang_internals.definition.wasm import RawWasmFunctionDef
|
|
30
|
+
from guppylang_internals.engine import DEF_STORE
|
|
31
|
+
from guppylang_internals.std._internal.checker import WasmCallChecker
|
|
32
|
+
from guppylang_internals.std._internal.compiler.wasm import (
|
|
33
|
+
WasmModuleCallCompiler,
|
|
34
|
+
WasmModuleDiscardCompiler,
|
|
35
|
+
WasmModuleInitCompiler,
|
|
36
|
+
)
|
|
37
|
+
from guppylang_internals.tys.arg import Argument
|
|
38
|
+
from guppylang_internals.tys.builtin import (
|
|
39
|
+
WasmModuleTypeDef,
|
|
40
|
+
)
|
|
41
|
+
from guppylang_internals.tys.param import Parameter
|
|
42
|
+
from guppylang_internals.tys.subst import Inst
|
|
43
|
+
from guppylang_internals.tys.ty import (
|
|
44
|
+
FuncInput,
|
|
45
|
+
FunctionType,
|
|
46
|
+
InputFlags,
|
|
47
|
+
NoneType,
|
|
48
|
+
NumericType,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
T = TypeVar("T")
|
|
52
|
+
P = ParamSpec("P")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_calling_frame() -> FrameType:
|
|
56
|
+
"""Finds the first frame that called this function outside the compiler modules."""
|
|
57
|
+
frame = inspect.currentframe()
|
|
58
|
+
while frame:
|
|
59
|
+
module = inspect.getmodule(frame)
|
|
60
|
+
if module is None:
|
|
61
|
+
return frame
|
|
62
|
+
if module.__file__ != __file__:
|
|
63
|
+
return frame
|
|
64
|
+
frame = frame.f_back
|
|
65
|
+
raise RuntimeError("Couldn't obtain stack frame for definition")
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def custom_function(
|
|
69
|
+
compiler: CustomInoutCallCompiler | None = None,
|
|
70
|
+
checker: CustomCallChecker | None = None,
|
|
71
|
+
higher_order_value: bool = True,
|
|
72
|
+
name: str = "",
|
|
73
|
+
signature: FunctionType | None = None,
|
|
74
|
+
) -> Callable[[Callable[P, T]], GuppyFunctionDefinition[P, T]]:
|
|
75
|
+
"""Decorator to add custom typing or compilation behaviour to function decls.
|
|
76
|
+
|
|
77
|
+
Optionally, usage of the function as a higher-order value can be disabled. In
|
|
78
|
+
that case, the function signature can be omitted if a custom call compiler is
|
|
79
|
+
provided.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
def dec(f: Callable[P, T]) -> GuppyFunctionDefinition[P, T]:
|
|
83
|
+
call_checker = checker or DefaultCallChecker()
|
|
84
|
+
func = RawCustomFunctionDef(
|
|
85
|
+
DefId.fresh(),
|
|
86
|
+
name or f.__name__,
|
|
87
|
+
None,
|
|
88
|
+
f,
|
|
89
|
+
call_checker,
|
|
90
|
+
compiler or NotImplementedCallCompiler(),
|
|
91
|
+
higher_order_value,
|
|
92
|
+
signature,
|
|
93
|
+
)
|
|
94
|
+
DEF_STORE.register_def(func, get_calling_frame())
|
|
95
|
+
return GuppyFunctionDefinition(func)
|
|
96
|
+
|
|
97
|
+
return dec
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def hugr_op(
|
|
101
|
+
op: Callable[[ht.FunctionType, Inst, CompilerContext], ops.DataflowOp],
|
|
102
|
+
checker: CustomCallChecker | None = None,
|
|
103
|
+
higher_order_value: bool = True,
|
|
104
|
+
name: str = "",
|
|
105
|
+
signature: FunctionType | None = None,
|
|
106
|
+
) -> Callable[[Callable[P, T]], GuppyFunctionDefinition[P, T]]:
|
|
107
|
+
"""Decorator to annotate function declarations as HUGR ops.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
op: A function that takes an instantiation of the type arguments as well as
|
|
111
|
+
the inferred input and output types and returns a concrete HUGR op.
|
|
112
|
+
checker: The custom call checker.
|
|
113
|
+
higher_order_value: Whether the function may be used as a higher-order
|
|
114
|
+
value.
|
|
115
|
+
name: The name of the function.
|
|
116
|
+
"""
|
|
117
|
+
return custom_function(OpCompiler(op), checker, higher_order_value, name, signature)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def extend_type(defn: TypeDef) -> Callable[[type], type]:
|
|
121
|
+
"""Decorator to add new instance functions to a type."""
|
|
122
|
+
|
|
123
|
+
def dec(c: type) -> type:
|
|
124
|
+
for val in c.__dict__.values():
|
|
125
|
+
if isinstance(val, GuppyDefinition):
|
|
126
|
+
DEF_STORE.register_impl(defn.id, val.wrapped.name, val.id)
|
|
127
|
+
return c
|
|
128
|
+
|
|
129
|
+
return dec
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def custom_type(
|
|
133
|
+
hugr_ty: ht.Type | Callable[[Sequence[Argument], CompilerContext], ht.Type],
|
|
134
|
+
name: str = "",
|
|
135
|
+
copyable: bool = True,
|
|
136
|
+
droppable: bool = True,
|
|
137
|
+
bound: ht.TypeBound | None = None,
|
|
138
|
+
params: Sequence[Parameter] | None = None,
|
|
139
|
+
) -> Callable[[type[T]], type[T]]:
|
|
140
|
+
"""Decorator to annotate a class definitions as Guppy types.
|
|
141
|
+
|
|
142
|
+
Requires the static Hugr translation of the type. Additionally, the type can be
|
|
143
|
+
marked as linear. All `@guppy` annotated functions on the class are turned into
|
|
144
|
+
instance functions.
|
|
145
|
+
|
|
146
|
+
For non-generic types, the Hugr representation can be passed as a static value.
|
|
147
|
+
For generic types, a callable may be passed that takes the type arguments of a
|
|
148
|
+
concrete instantiation.
|
|
149
|
+
"""
|
|
150
|
+
mk_hugr_ty = (
|
|
151
|
+
(lambda args, ctx: hugr_ty) if isinstance(hugr_ty, ht.Type) else hugr_ty
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
def dec(c: type[T]) -> type[T]:
|
|
155
|
+
defn = OpaqueTypeDef(
|
|
156
|
+
DefId.fresh(),
|
|
157
|
+
name or c.__name__,
|
|
158
|
+
None,
|
|
159
|
+
params or [],
|
|
160
|
+
not copyable,
|
|
161
|
+
not droppable,
|
|
162
|
+
mk_hugr_ty,
|
|
163
|
+
bound,
|
|
164
|
+
)
|
|
165
|
+
DEF_STORE.register_def(defn, get_calling_frame())
|
|
166
|
+
for val in c.__dict__.values():
|
|
167
|
+
if isinstance(val, GuppyDefinition):
|
|
168
|
+
DEF_STORE.register_impl(defn.id, val.wrapped.name, val.id)
|
|
169
|
+
# We're pretending to return the class unchanged, but in fact we return
|
|
170
|
+
# a `GuppyDefinition` that handles the comptime logic
|
|
171
|
+
return GuppyDefinition(defn) # type: ignore[return-value]
|
|
172
|
+
|
|
173
|
+
return dec
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def wasm_module(
|
|
177
|
+
filename: str, filehash: int
|
|
178
|
+
) -> Callable[[builtins.type[T]], GuppyDefinition]:
|
|
179
|
+
def dec(cls: builtins.type[T]) -> GuppyDefinition:
|
|
180
|
+
# N.B. Only one module per file and vice-versa
|
|
181
|
+
wasm_module = WasmModuleTypeDef(
|
|
182
|
+
DefId.fresh(),
|
|
183
|
+
cls.__name__,
|
|
184
|
+
None,
|
|
185
|
+
filename,
|
|
186
|
+
filehash,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
wasm_module_ty = wasm_module.check_instantiate([], None)
|
|
190
|
+
|
|
191
|
+
DEF_STORE.register_def(wasm_module, get_calling_frame())
|
|
192
|
+
for val in cls.__dict__.values():
|
|
193
|
+
if isinstance(val, GuppyDefinition):
|
|
194
|
+
DEF_STORE.register_impl(wasm_module.id, val.wrapped.name, val.id)
|
|
195
|
+
# Add a constructor to the class
|
|
196
|
+
call_method = CustomFunctionDef(
|
|
197
|
+
DefId.fresh(),
|
|
198
|
+
"__new__",
|
|
199
|
+
None,
|
|
200
|
+
FunctionType(
|
|
201
|
+
[FuncInput(NumericType(NumericType.Kind.Nat), flags=InputFlags.Owned)],
|
|
202
|
+
wasm_module_ty,
|
|
203
|
+
),
|
|
204
|
+
DefaultCallChecker(),
|
|
205
|
+
WasmModuleInitCompiler(),
|
|
206
|
+
True,
|
|
207
|
+
GlobalConstId.fresh(f"{cls.__name__}.__new__"),
|
|
208
|
+
True,
|
|
209
|
+
)
|
|
210
|
+
discard = CustomFunctionDef(
|
|
211
|
+
DefId.fresh(),
|
|
212
|
+
"discard",
|
|
213
|
+
None,
|
|
214
|
+
FunctionType([FuncInput(wasm_module_ty, InputFlags.Owned)], NoneType()),
|
|
215
|
+
DefaultCallChecker(),
|
|
216
|
+
WasmModuleDiscardCompiler(),
|
|
217
|
+
False,
|
|
218
|
+
GlobalConstId.fresh(f"{cls.__name__}.__discard__"),
|
|
219
|
+
True,
|
|
220
|
+
)
|
|
221
|
+
DEF_STORE.register_def(call_method, get_calling_frame())
|
|
222
|
+
DEF_STORE.register_impl(wasm_module.id, "__new__", call_method.id)
|
|
223
|
+
DEF_STORE.register_def(discard, get_calling_frame())
|
|
224
|
+
DEF_STORE.register_impl(wasm_module.id, "discard", discard.id)
|
|
225
|
+
|
|
226
|
+
return GuppyDefinition(wasm_module)
|
|
227
|
+
|
|
228
|
+
return dec
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
def wasm(f: Callable[P, T]) -> GuppyFunctionDefinition[P, T]:
|
|
232
|
+
func = RawWasmFunctionDef(
|
|
233
|
+
DefId.fresh(),
|
|
234
|
+
f.__name__,
|
|
235
|
+
None,
|
|
236
|
+
f,
|
|
237
|
+
WasmCallChecker(),
|
|
238
|
+
WasmModuleCallCompiler(f.__name__),
|
|
239
|
+
True,
|
|
240
|
+
signature=None,
|
|
241
|
+
)
|
|
242
|
+
DEF_STORE.register_def(func, get_calling_frame())
|
|
243
|
+
return GuppyFunctionDefinition(func)
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
# TODO sphinx hack for custom decorators
|
|
File without changes
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
import itertools
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from collections.abc import Iterator, Sequence
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, ClassVar, TypeAlias
|
|
7
|
+
|
|
8
|
+
from hugr.build.dfg import DefinitionBuilder, OpVar
|
|
9
|
+
|
|
10
|
+
from guppylang_internals.diagnostic import Fatal
|
|
11
|
+
from guppylang_internals.span import SourceMap
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from guppylang_internals.checker.core import Globals
|
|
15
|
+
from guppylang_internals.compiler.core import (
|
|
16
|
+
CompilerContext,
|
|
17
|
+
PartiallyMonomorphizedArgs,
|
|
18
|
+
)
|
|
19
|
+
from guppylang_internals.tys.param import Parameter
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
RawDef: TypeAlias = "ParsableDef | ParsedDef"
|
|
23
|
+
ParsedDef: TypeAlias = "CheckableDef | CheckedDef"
|
|
24
|
+
CheckedDef: TypeAlias = "CompilableDef | MonomorphizableDef | CompiledDef"
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@dataclass(frozen=True)
|
|
28
|
+
class DefId:
|
|
29
|
+
"""Unique identifier for definitions across modules.
|
|
30
|
+
|
|
31
|
+
This id is persistent across all compilation stages. It can be used to identify a
|
|
32
|
+
definition at any step in the compilation pipeline.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
id: An integer uniquely identifying the definition.
|
|
36
|
+
module: The module where the definition was defined.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
id: int
|
|
40
|
+
|
|
41
|
+
_ids: ClassVar[Iterator[int]] = itertools.count()
|
|
42
|
+
|
|
43
|
+
@classmethod
|
|
44
|
+
def fresh(cls) -> "DefId":
|
|
45
|
+
return DefId(next(cls._ids))
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
@dataclass(frozen=True)
|
|
49
|
+
class Definition(ABC):
|
|
50
|
+
"""Abstract base class for user-defined objects on module-level.
|
|
51
|
+
|
|
52
|
+
Each definition is identified by a globally unique id. Furthermore, we store the
|
|
53
|
+
user-picked name for the defined object and an optional AST node for the definition
|
|
54
|
+
location.
|
|
55
|
+
|
|
56
|
+
Args:
|
|
57
|
+
id: The unique definition identifier.
|
|
58
|
+
name: The name of the definition.
|
|
59
|
+
defined_at: The AST node where the definition was defined.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
id: DefId
|
|
63
|
+
name: str
|
|
64
|
+
defined_at: ast.AST | None
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
@abstractmethod
|
|
68
|
+
def description(self) -> str:
|
|
69
|
+
"""Description of this definition to be used in messages to the user.
|
|
70
|
+
|
|
71
|
+
The returned text should fit into messages of the following form: "expected
|
|
72
|
+
a function, but got {description of this definition} instead".
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ParsableDef(Definition):
|
|
77
|
+
"""Abstract base class for raw definitions that still require parsing.
|
|
78
|
+
|
|
79
|
+
For example, raw function definitions first need to parse their signature and check
|
|
80
|
+
that all types are valid. The result of parsing should be a definition that is ready
|
|
81
|
+
to be checked.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
id: The unique definition identifier.
|
|
85
|
+
name: The name of the definition.
|
|
86
|
+
defined_at: The AST node where the definition was defined.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
def parse(self, globals: "Globals", sources: SourceMap) -> ParsedDef:
|
|
91
|
+
"""Performs parsing and validation, returning a definition that can be checked.
|
|
92
|
+
|
|
93
|
+
The provided globals contain all other raw definitions that have been defined.
|
|
94
|
+
"""
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class CheckableDef(Definition):
|
|
98
|
+
"""Abstract base class for definitions that still need to be checked.
|
|
99
|
+
|
|
100
|
+
The result of checking should be a definition that is ready to be compiled to Hugr.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
id: The unique definition identifier.
|
|
104
|
+
name: The name of the definition.
|
|
105
|
+
defined_at: The AST node where the definition was defined.
|
|
106
|
+
"""
|
|
107
|
+
|
|
108
|
+
@abstractmethod
|
|
109
|
+
def check(self, globals: "Globals") -> CheckedDef:
|
|
110
|
+
"""Type checks the definition.
|
|
111
|
+
|
|
112
|
+
The provided globals contain all other parsed definitions that have been
|
|
113
|
+
defined.
|
|
114
|
+
|
|
115
|
+
Returns a checked version of the definition that can be compiled to Hugr.
|
|
116
|
+
"""
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class CompilableDef(Definition):
|
|
120
|
+
"""Abstract base class for definitions that still need to be compiled to Hugr.
|
|
121
|
+
|
|
122
|
+
The result of compilation should be a `CompiledDef` with a pointer to the Hugr node
|
|
123
|
+
that was created for this definition.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
id: The unique definition identifier.
|
|
127
|
+
name: The name of the definition.
|
|
128
|
+
defined_at: The AST node where the definition was defined.
|
|
129
|
+
"""
|
|
130
|
+
|
|
131
|
+
@abstractmethod
|
|
132
|
+
def compile_outer(
|
|
133
|
+
self, module: DefinitionBuilder[OpVar], ctx: "CompilerContext"
|
|
134
|
+
) -> "CompiledDef":
|
|
135
|
+
"""Adds a Hugr node for the definition to the provided Hugr module.
|
|
136
|
+
|
|
137
|
+
Note that is not required to fill in the contents of the node. At this point,
|
|
138
|
+
we don't have access to the globals since they have not all been compiled yet.
|
|
139
|
+
|
|
140
|
+
See `CompiledDef.compile_inner()` for the hook to compile the inside of the
|
|
141
|
+
node. This two-step process enables things like mutual recursion.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class MonomorphizableDef(Definition):
|
|
146
|
+
"""Abstract base class for definitions that require monomorphization when compiling
|
|
147
|
+
to Hugr.
|
|
148
|
+
|
|
149
|
+
Args:
|
|
150
|
+
id: The unique definition identifier.
|
|
151
|
+
name: The name of the definition.
|
|
152
|
+
defined_at: The AST node where the definition was defined.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
@property
|
|
156
|
+
@abstractmethod
|
|
157
|
+
def params(self) -> "Sequence[Parameter]":
|
|
158
|
+
"""Generic parameters of this definition."""
|
|
159
|
+
|
|
160
|
+
@abstractmethod
|
|
161
|
+
def monomorphize(
|
|
162
|
+
self,
|
|
163
|
+
module: DefinitionBuilder[OpVar],
|
|
164
|
+
mono_args: "PartiallyMonomorphizedArgs",
|
|
165
|
+
ctx: "CompilerContext",
|
|
166
|
+
) -> "MonomorphizedDef":
|
|
167
|
+
"""Adds a Hugr node for the (partially) monomorphized definition to the provided
|
|
168
|
+
Hugr module.
|
|
169
|
+
|
|
170
|
+
See `MonomorphizedDef.compile_inner()` for the hook to compile the inside of the
|
|
171
|
+
node. This two-step process enables things like mutual recursion.
|
|
172
|
+
"""
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
class CompiledDef(Definition):
|
|
176
|
+
"""Abstract base class for definitions that have been added to a Hugr.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
id: The unique definition identifier.
|
|
180
|
+
name: The name of the definition.
|
|
181
|
+
defined_at: The AST node where the definition was defined.
|
|
182
|
+
"""
|
|
183
|
+
|
|
184
|
+
def compile_inner(self, ctx: "CompilerContext") -> None:
|
|
185
|
+
"""Optional hook that is called to fill in the content of the Hugr node.
|
|
186
|
+
|
|
187
|
+
Opposed to `CompilableDef.compile()`, we have access to all other compiled
|
|
188
|
+
definitions here, which allows things like mutual recursion.
|
|
189
|
+
"""
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
@dataclass(frozen=True)
|
|
193
|
+
class MonomorphizedDef(CompiledDef):
|
|
194
|
+
"""Abstract base class for definitions that have been added to a Hugr and have been
|
|
195
|
+
partially monomorphized.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
id: The unique definition identifier.
|
|
199
|
+
name: The name of the definition. This will be the same for all monomorphized
|
|
200
|
+
variants of the definition.
|
|
201
|
+
defined_at: The AST node where the original polymorphic definition was defined.
|
|
202
|
+
mono_args: Partial monomorphization of the generic parameters.
|
|
203
|
+
"""
|
|
204
|
+
|
|
205
|
+
mono_args: "PartiallyMonomorphizedArgs"
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@dataclass(frozen=True)
|
|
209
|
+
class UnknownSourceError(Fatal):
|
|
210
|
+
title: ClassVar[str] = "Cannot find source"
|
|
211
|
+
message: ClassVar[str] = (
|
|
212
|
+
"Unable to look up the source code for Python object `{obj}`"
|
|
213
|
+
)
|
|
214
|
+
obj: object
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import ast
|
|
2
|
+
from dataclasses import dataclass, field
|
|
3
|
+
|
|
4
|
+
from hugr import Node, Wire
|
|
5
|
+
from hugr import val as hv
|
|
6
|
+
from hugr.build.dfg import DefinitionBuilder, OpVar
|
|
7
|
+
|
|
8
|
+
from guppylang_internals.ast_util import AstNode
|
|
9
|
+
from guppylang_internals.checker.core import Globals
|
|
10
|
+
from guppylang_internals.compiler.core import CompilerContext, DFContainer
|
|
11
|
+
from guppylang_internals.definition.common import CompilableDef, ParsableDef
|
|
12
|
+
from guppylang_internals.definition.value import (
|
|
13
|
+
CompiledHugrNodeDef,
|
|
14
|
+
CompiledValueDef,
|
|
15
|
+
ValueDef,
|
|
16
|
+
)
|
|
17
|
+
from guppylang_internals.span import SourceMap
|
|
18
|
+
from guppylang_internals.tys.parsing import type_from_ast
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class RawConstDef(ParsableDef):
|
|
23
|
+
"""A raw constant definition as provided by the user."""
|
|
24
|
+
|
|
25
|
+
type_ast: ast.expr
|
|
26
|
+
value: hv.Value
|
|
27
|
+
|
|
28
|
+
description: str = field(default="constant", init=False)
|
|
29
|
+
|
|
30
|
+
def parse(self, globals: Globals, sources: SourceMap) -> "ConstDef":
|
|
31
|
+
"""Parses and checks the user-provided signature of the function."""
|
|
32
|
+
return ConstDef(
|
|
33
|
+
self.id,
|
|
34
|
+
self.name,
|
|
35
|
+
self.defined_at,
|
|
36
|
+
type_from_ast(self.type_ast, globals, {}),
|
|
37
|
+
self.type_ast,
|
|
38
|
+
self.value,
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
@dataclass(frozen=True)
|
|
43
|
+
class ConstDef(RawConstDef, ValueDef, CompilableDef):
|
|
44
|
+
"""A constant with a checked type."""
|
|
45
|
+
|
|
46
|
+
def compile_outer(
|
|
47
|
+
self, graph: DefinitionBuilder[OpVar], ctx: CompilerContext
|
|
48
|
+
) -> "CompiledConstDef":
|
|
49
|
+
const_node = graph.add_const(self.value)
|
|
50
|
+
return CompiledConstDef(
|
|
51
|
+
self.id,
|
|
52
|
+
self.name,
|
|
53
|
+
self.defined_at,
|
|
54
|
+
self.ty,
|
|
55
|
+
self.type_ast,
|
|
56
|
+
self.value,
|
|
57
|
+
const_node,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass(frozen=True)
|
|
62
|
+
class CompiledConstDef(ConstDef, CompiledValueDef, CompiledHugrNodeDef):
|
|
63
|
+
"""A constant that has been compiled to a Hugr node."""
|
|
64
|
+
|
|
65
|
+
const_node: Node
|
|
66
|
+
|
|
67
|
+
@property
|
|
68
|
+
def hugr_node(self) -> Node:
|
|
69
|
+
"""The Hugr node this definition was compiled into."""
|
|
70
|
+
return self.const_node
|
|
71
|
+
|
|
72
|
+
def load(self, dfg: DFContainer, ctx: CompilerContext, node: AstNode) -> Wire:
|
|
73
|
+
"""Loads the extern value into a local Hugr dataflow graph."""
|
|
74
|
+
return dfg.builder.load(self.const_node)
|