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,178 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
3
|
+
|
|
4
|
+
from guppylang_internals.diagnostic import Error, Help, Note
|
|
5
|
+
|
|
6
|
+
if TYPE_CHECKING:
|
|
7
|
+
from guppylang_internals.definition.parameter import ParamDef
|
|
8
|
+
from guppylang_internals.tys.ty import Type
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class WrongNumberOfTypeArgsError(Error):
|
|
13
|
+
title: ClassVar[str] = "" # Custom implementation in `rendered_title`
|
|
14
|
+
expected: int
|
|
15
|
+
actual: int
|
|
16
|
+
type_name: str
|
|
17
|
+
|
|
18
|
+
@property
|
|
19
|
+
def rendered_title(self) -> str:
|
|
20
|
+
if self.expected == 0:
|
|
21
|
+
return "Non-parametric type"
|
|
22
|
+
elif self.expected > self.actual:
|
|
23
|
+
return "Missing type arguments"
|
|
24
|
+
else:
|
|
25
|
+
return "Too many type arguments"
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def rendered_span_label(self) -> str:
|
|
29
|
+
if self.expected == 0:
|
|
30
|
+
return f"Type `{self.type_name}` is not parametric"
|
|
31
|
+
diff = self.expected - self.actual
|
|
32
|
+
msg = "Unexpected " if diff < 0 else "Missing "
|
|
33
|
+
msg += "type arguments " if abs(diff) > 1 else "type argument "
|
|
34
|
+
msg += (
|
|
35
|
+
f"for type `{self.type_name}` (expected {self.expected}, got {self.actual})"
|
|
36
|
+
)
|
|
37
|
+
return msg
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass(frozen=True)
|
|
41
|
+
class InvalidTypeArgError(Error):
|
|
42
|
+
title: ClassVar[str] = "Invalid type argument"
|
|
43
|
+
span_label: ClassVar[str] = "Not a valid type argument"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass(frozen=True)
|
|
47
|
+
class IllegalComptimeTypeArgError(Error):
|
|
48
|
+
title: ClassVar[str] = "Invalid type argument"
|
|
49
|
+
span_label: ClassVar[str] = (
|
|
50
|
+
"Comptime expression evaluating to `{obj}` is not a valid type argument"
|
|
51
|
+
)
|
|
52
|
+
obj: object
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
@dataclass(frozen=True)
|
|
56
|
+
class ModuleMemberNotFoundError(Error):
|
|
57
|
+
# TODO: Unify with the definition in expression checker once merged
|
|
58
|
+
title: ClassVar[str] = "Not found in module"
|
|
59
|
+
span_label: ClassVar[str] = "Module `{module_name}` has no member `{member}`"
|
|
60
|
+
module_name: str
|
|
61
|
+
member: str
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@dataclass(frozen=True)
|
|
65
|
+
class HigherKindedTypeVarError(Error):
|
|
66
|
+
title: ClassVar[str] = "Not parametric"
|
|
67
|
+
span_label: ClassVar[str] = (
|
|
68
|
+
"Type variable `{var_def.name}` doesn't take type arguments"
|
|
69
|
+
)
|
|
70
|
+
var_def: "ParamDef"
|
|
71
|
+
|
|
72
|
+
@dataclass(frozen=True)
|
|
73
|
+
class Explain(Note):
|
|
74
|
+
message: ClassVar[str] = "Higher-kinded types are not supported"
|
|
75
|
+
|
|
76
|
+
def __post_init__(self) -> None:
|
|
77
|
+
self.add_sub_diagnostic(HigherKindedTypeVarError.Explain(None))
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@dataclass(frozen=True)
|
|
81
|
+
class FreeTypeVarError(Error):
|
|
82
|
+
title: ClassVar[str] = "Free type variable"
|
|
83
|
+
span_label: ClassVar[str] = "Type variable `{var_def.name}` is unbound"
|
|
84
|
+
var_def: "ParamDef"
|
|
85
|
+
|
|
86
|
+
@dataclass(frozen=True)
|
|
87
|
+
class Explain(Note):
|
|
88
|
+
message: ClassVar[str] = (
|
|
89
|
+
"Only struct and function definitions can be generic. Other generic values "
|
|
90
|
+
"or nested types are not supported."
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
def __post_init__(self) -> None:
|
|
94
|
+
self.add_sub_diagnostic(FreeTypeVarError.Explain(None))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@dataclass(frozen=True)
|
|
98
|
+
class InvalidTypeError(Error):
|
|
99
|
+
title: ClassVar[str] = "Invalid type"
|
|
100
|
+
span_label: ClassVar[str] = "Not a valid type"
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
@dataclass(frozen=True)
|
|
104
|
+
class InvalidCallableTypeError(Error):
|
|
105
|
+
title: ClassVar[str] = "Invalid type"
|
|
106
|
+
span_label: ClassVar[str] = "Invalid function type"
|
|
107
|
+
|
|
108
|
+
@dataclass(frozen=True)
|
|
109
|
+
class Explain(Help):
|
|
110
|
+
message: ClassVar[str] = (
|
|
111
|
+
"Function types are specified as follows: "
|
|
112
|
+
"`Callable[[<arguments>], <return type>]`"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
def __post_init__(self) -> None:
|
|
116
|
+
self.add_sub_diagnostic(InvalidCallableTypeError.Explain(None))
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
@dataclass(frozen=True)
|
|
120
|
+
class NonLinearOwnedError(Error):
|
|
121
|
+
title: ClassVar[str] = "Invalid annotation"
|
|
122
|
+
span_label: ClassVar[str] = "Classical type `{ty}` cannot be owned"
|
|
123
|
+
ty: "Type"
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@dataclass(frozen=True)
|
|
127
|
+
class LinearConstParamError(Error):
|
|
128
|
+
title: ClassVar[str] = "Invalid parameter"
|
|
129
|
+
span_label: ClassVar[str] = (
|
|
130
|
+
"Non-{thing} type `{ty}` is not allowed as a generic parameter"
|
|
131
|
+
)
|
|
132
|
+
ty: "Type"
|
|
133
|
+
|
|
134
|
+
@property
|
|
135
|
+
def thing(self) -> str:
|
|
136
|
+
return "copyable" if not self.ty.copyable else "droppable"
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
@dataclass(frozen=True)
|
|
140
|
+
class LinearComptimeError(Error):
|
|
141
|
+
title: ClassVar[str] = "Invalid annotation"
|
|
142
|
+
span_label: ClassVar[str] = (
|
|
143
|
+
"Non-{thing} type `{ty}` is not allowed as a comptime argument"
|
|
144
|
+
)
|
|
145
|
+
ty: "Type"
|
|
146
|
+
|
|
147
|
+
@property
|
|
148
|
+
def thing(self) -> str:
|
|
149
|
+
return "copyable" if not self.ty.copyable else "droppable"
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
@dataclass(frozen=True)
|
|
153
|
+
class CallableComptimeError(Error):
|
|
154
|
+
title: ClassVar[str] = "Invalid annotation"
|
|
155
|
+
span_label: ClassVar[str] = (
|
|
156
|
+
"Comptime annotations are only allowed for named top-level function arguments"
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@dataclass(frozen=True)
|
|
161
|
+
class ComptimeArgShadowError(Error):
|
|
162
|
+
title: ClassVar[str] = "Shadowed type parameter"
|
|
163
|
+
span_label: ClassVar[str] = (
|
|
164
|
+
"Comptime argument `{arg}` shadows previously used parameter with the same name"
|
|
165
|
+
)
|
|
166
|
+
arg: str
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@dataclass(frozen=True)
|
|
170
|
+
class InvalidFlagError(Error):
|
|
171
|
+
title: ClassVar[str] = "Invalid annotation"
|
|
172
|
+
span_label: ClassVar[str] = "Invalid type annotation"
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@dataclass(frozen=True)
|
|
176
|
+
class FlagNotAllowedError(Error):
|
|
177
|
+
title: ClassVar[str] = "Invalid annotation"
|
|
178
|
+
span_label: ClassVar[str] = "`@` type annotations are not allowed in this position"
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from collections.abc import Sequence
|
|
3
|
+
from dataclasses import dataclass, field
|
|
4
|
+
from typing import TYPE_CHECKING, TypeAlias
|
|
5
|
+
|
|
6
|
+
from hugr import tys as ht
|
|
7
|
+
from typing_extensions import Self
|
|
8
|
+
|
|
9
|
+
from guppylang_internals.ast_util import AstNode
|
|
10
|
+
from guppylang_internals.checker.errors.generic import ExpectedError
|
|
11
|
+
from guppylang_internals.checker.errors.type_errors import TypeMismatchError
|
|
12
|
+
from guppylang_internals.error import GuppyError, GuppyTypeError, InternalGuppyError
|
|
13
|
+
from guppylang_internals.tys.arg import Argument, ConstArg, TypeArg
|
|
14
|
+
from guppylang_internals.tys.common import ToHugr, ToHugrContext
|
|
15
|
+
from guppylang_internals.tys.const import BoundConstVar, ExistentialConstVar
|
|
16
|
+
from guppylang_internals.tys.errors import WrongNumberOfTypeArgsError
|
|
17
|
+
from guppylang_internals.tys.var import ExistentialVar
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from guppylang_internals.tys.ty import Type
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# We define the `Parameter` type as a union of all `ParameterBase` subclasses defined
|
|
24
|
+
# below. This models an algebraic data type and enables exhaustiveness checking in
|
|
25
|
+
# pattern matches etc.
|
|
26
|
+
# Note that this might become obsolete in case the `@sealed` decorator is added:
|
|
27
|
+
# * https://peps.python.org/pep-0622/#sealed-classes-as-algebraic-data-types
|
|
28
|
+
# * https://github.com/johnthagen/sealed-typing-pep
|
|
29
|
+
Parameter: TypeAlias = "TypeParam | ConstParam"
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@dataclass(frozen=True)
|
|
33
|
+
class ParameterBase(ToHugr[ht.TypeParam], ABC):
|
|
34
|
+
"""Abstract base class for parameters used in function and type definitions.
|
|
35
|
+
|
|
36
|
+
For example, when defining a struct type
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
@guppy.struct
|
|
40
|
+
class Foo[T, n: int]:
|
|
41
|
+
...
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
we generate an `StructDef` that depends on the parameters `T` and `n`. From
|
|
45
|
+
this, we obtain a proper `StructType` by providing arguments that are substituted
|
|
46
|
+
for the parameters (for example `Foo[int, 42]`).
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
idx: int
|
|
50
|
+
name: str
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def with_idx(self, idx: int) -> Self:
|
|
54
|
+
"""Returns a copy of the parameter with a new index."""
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
def check_arg(self, arg: Argument, loc: AstNode | None = None) -> Argument:
|
|
58
|
+
"""Checks that this parameter can be instantiated with a given argument.
|
|
59
|
+
|
|
60
|
+
Raises a user error if the argument is not valid.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
@abstractmethod
|
|
64
|
+
def to_existential(self) -> tuple[Argument, ExistentialVar]:
|
|
65
|
+
"""Creates a fresh existential variable that can be instantiated for this
|
|
66
|
+
parameter.
|
|
67
|
+
|
|
68
|
+
Returns both the argument and the created variable.
|
|
69
|
+
"""
|
|
70
|
+
|
|
71
|
+
@abstractmethod
|
|
72
|
+
def to_bound(self, idx: int | None = None) -> Argument:
|
|
73
|
+
"""Creates a bound variable with a given index that can be instantiated for this
|
|
74
|
+
parameter.
|
|
75
|
+
"""
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
@dataclass(frozen=True)
|
|
79
|
+
class TypeParam(ParameterBase):
|
|
80
|
+
"""A parameter of kind type. Used to define generic functions and types."""
|
|
81
|
+
|
|
82
|
+
must_be_copyable: bool
|
|
83
|
+
must_be_droppable: bool
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def can_be_linear(self) -> bool:
|
|
87
|
+
"""Whether this type should be treated linearly."""
|
|
88
|
+
return not self.must_be_copyable and not self.must_be_droppable
|
|
89
|
+
|
|
90
|
+
def with_idx(self, idx: int) -> "TypeParam":
|
|
91
|
+
"""Returns a copy of the parameter with a new index."""
|
|
92
|
+
return TypeParam(idx, self.name, self.must_be_copyable, self.must_be_droppable)
|
|
93
|
+
|
|
94
|
+
def check_arg(self, arg: Argument, loc: AstNode | None = None) -> TypeArg:
|
|
95
|
+
"""Checks that this parameter can be instantiated with a given argument.
|
|
96
|
+
|
|
97
|
+
Raises a user error if the argument is not valid.
|
|
98
|
+
"""
|
|
99
|
+
match arg:
|
|
100
|
+
case ConstArg(const):
|
|
101
|
+
err = ExpectedError(loc, "a type", got=f"value of type `{const.ty}`")
|
|
102
|
+
raise GuppyTypeError(err)
|
|
103
|
+
case TypeArg(ty):
|
|
104
|
+
if self.must_be_copyable and not ty.copyable:
|
|
105
|
+
err = ExpectedError(
|
|
106
|
+
loc,
|
|
107
|
+
"a copyable type",
|
|
108
|
+
got=f"type `{ty}` which is not implicitly copyable",
|
|
109
|
+
)
|
|
110
|
+
raise GuppyTypeError(err)
|
|
111
|
+
if self.must_be_droppable and not ty.droppable:
|
|
112
|
+
err = ExpectedError(
|
|
113
|
+
loc,
|
|
114
|
+
"a droppable type",
|
|
115
|
+
got=f"type `{ty}` which is not implicitly droppable",
|
|
116
|
+
)
|
|
117
|
+
raise GuppyTypeError(err)
|
|
118
|
+
return arg
|
|
119
|
+
|
|
120
|
+
def to_existential(self) -> tuple[Argument, ExistentialVar]:
|
|
121
|
+
"""Creates a fresh existential variable that can be instantiated for this
|
|
122
|
+
parameter.
|
|
123
|
+
|
|
124
|
+
Returns both the argument and the created variable.
|
|
125
|
+
"""
|
|
126
|
+
from guppylang_internals.tys.ty import ExistentialTypeVar
|
|
127
|
+
|
|
128
|
+
var = ExistentialTypeVar.fresh(
|
|
129
|
+
self.name, self.must_be_copyable, self.must_be_droppable
|
|
130
|
+
)
|
|
131
|
+
return TypeArg(var), var
|
|
132
|
+
|
|
133
|
+
def to_bound(self, idx: int | None = None) -> TypeArg:
|
|
134
|
+
"""Creates a bound variable with a given index that can be instantiated for this
|
|
135
|
+
parameter.
|
|
136
|
+
"""
|
|
137
|
+
from guppylang_internals.tys.ty import BoundTypeVar
|
|
138
|
+
|
|
139
|
+
if idx is None:
|
|
140
|
+
idx = self.idx
|
|
141
|
+
return TypeArg(
|
|
142
|
+
BoundTypeVar(self.name, idx, self.must_be_copyable, self.must_be_droppable)
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
def to_hugr(self, ctx: ToHugrContext) -> ht.TypeParam:
|
|
146
|
+
"""Computes the Hugr representation of the parameter."""
|
|
147
|
+
return ht.TypeTypeParam(
|
|
148
|
+
bound=ht.TypeBound.Linear if self.can_be_linear else ht.TypeBound.Copyable
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
def __str__(self) -> str:
|
|
152
|
+
"""User-facing string representation of the parameter."""
|
|
153
|
+
return self.name
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
@dataclass(frozen=True)
|
|
157
|
+
class ConstParam(ParameterBase):
|
|
158
|
+
"""A parameter of kind constant. Used to define fixed-size arrays etc."""
|
|
159
|
+
|
|
160
|
+
ty: "Type"
|
|
161
|
+
|
|
162
|
+
#: Marker to annotate if this parameter was implicitly generated by a `@comptime`
|
|
163
|
+
#: annotated argument in a function signature.
|
|
164
|
+
from_comptime_arg: bool = field(default=False, kw_only=True)
|
|
165
|
+
|
|
166
|
+
def __post_init__(self) -> None:
|
|
167
|
+
if self.ty.unsolved_vars:
|
|
168
|
+
raise InternalGuppyError(
|
|
169
|
+
"Attempted to create constant param with unsolved type"
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
def with_idx(self, idx: int) -> "ConstParam":
|
|
173
|
+
"""Returns a copy of the parameter with a new index."""
|
|
174
|
+
return ConstParam(idx, self.name, self.ty)
|
|
175
|
+
|
|
176
|
+
def check_arg(self, arg: Argument, loc: AstNode | None = None) -> ConstArg:
|
|
177
|
+
"""Checks that this parameter can be instantiated with a given argument.
|
|
178
|
+
|
|
179
|
+
Raises a user error if the argument is not valid.
|
|
180
|
+
"""
|
|
181
|
+
match arg:
|
|
182
|
+
case ConstArg(const):
|
|
183
|
+
if const.ty != self.ty:
|
|
184
|
+
raise GuppyTypeError(
|
|
185
|
+
TypeMismatchError(loc, self.ty, const.ty, kind="argument")
|
|
186
|
+
)
|
|
187
|
+
return arg
|
|
188
|
+
case TypeArg(ty=ty):
|
|
189
|
+
err = ExpectedError(
|
|
190
|
+
loc, f"expression of type `{self.ty}`", got=f"type `{ty}`"
|
|
191
|
+
)
|
|
192
|
+
raise GuppyTypeError(err)
|
|
193
|
+
|
|
194
|
+
def to_existential(self) -> tuple[Argument, ExistentialVar]:
|
|
195
|
+
"""Creates a fresh existential variable that can be instantiated for this
|
|
196
|
+
parameter.
|
|
197
|
+
|
|
198
|
+
Returns both the argument and the created variable.
|
|
199
|
+
"""
|
|
200
|
+
var = ExistentialConstVar.fresh(self.name, self.ty)
|
|
201
|
+
return ConstArg(var), var
|
|
202
|
+
|
|
203
|
+
def to_bound(self, idx: int | None = None) -> ConstArg:
|
|
204
|
+
"""Creates a bound variable with a given index that can be instantiated for this
|
|
205
|
+
parameter.
|
|
206
|
+
"""
|
|
207
|
+
if idx is None:
|
|
208
|
+
idx = self.idx
|
|
209
|
+
return ConstArg(BoundConstVar(self.ty, self.name, idx))
|
|
210
|
+
|
|
211
|
+
def to_hugr(self, ctx: ToHugrContext) -> ht.TypeParam:
|
|
212
|
+
"""Computes the Hugr representation of the parameter."""
|
|
213
|
+
from guppylang_internals.tys.ty import NumericType
|
|
214
|
+
|
|
215
|
+
match self.ty:
|
|
216
|
+
case NumericType(kind=NumericType.Kind.Nat):
|
|
217
|
+
return ht.BoundedNatParam(upper_bound=None)
|
|
218
|
+
case _:
|
|
219
|
+
raise InternalGuppyError(
|
|
220
|
+
"Tried to convert non-nat const type parameter to Hugr. This "
|
|
221
|
+
"should have been monomorphized away."
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
def __str__(self) -> str:
|
|
225
|
+
"""User-facing string representation of the parameter."""
|
|
226
|
+
return f"{self.name}: {self.ty}"
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
def check_all_args(
|
|
230
|
+
params: Sequence[Parameter],
|
|
231
|
+
args: Sequence[Argument],
|
|
232
|
+
type_name: str,
|
|
233
|
+
loc: AstNode | None = None,
|
|
234
|
+
) -> None:
|
|
235
|
+
"""Checks a list of arguments against the given parameters.
|
|
236
|
+
|
|
237
|
+
Raises a user error if number of arguments doesn't match or one of the argument is
|
|
238
|
+
invalid.
|
|
239
|
+
"""
|
|
240
|
+
exp, act = len(params), len(args)
|
|
241
|
+
if exp != act:
|
|
242
|
+
# TODO: Adjust the error span to only point to the offending arguments (similar
|
|
243
|
+
# to how we deal with call args in the expression checker). This requires
|
|
244
|
+
# threading the type arg spans down to this point
|
|
245
|
+
raise GuppyError(WrongNumberOfTypeArgsError(loc, exp, act, type_name))
|
|
246
|
+
|
|
247
|
+
# Now check that the kinds match up
|
|
248
|
+
for param, arg in zip(params, args, strict=True):
|
|
249
|
+
# TODO: The error location is bad. We want the location of `arg`, not of the
|
|
250
|
+
# whole thing.
|
|
251
|
+
param.check_arg(arg, loc)
|