guppylang-internals 0.25.0__py3-none-any.whl → 0.27.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.
Files changed (49) hide show
  1. guppylang_internals/__init__.py +1 -1
  2. guppylang_internals/cfg/builder.py +20 -2
  3. guppylang_internals/cfg/cfg.py +3 -0
  4. guppylang_internals/checker/cfg_checker.py +6 -0
  5. guppylang_internals/checker/core.py +1 -2
  6. guppylang_internals/checker/errors/linearity.py +6 -2
  7. guppylang_internals/checker/errors/wasm.py +7 -4
  8. guppylang_internals/checker/expr_checker.py +39 -19
  9. guppylang_internals/checker/func_checker.py +17 -13
  10. guppylang_internals/checker/linearity_checker.py +2 -10
  11. guppylang_internals/checker/modifier_checker.py +6 -2
  12. guppylang_internals/checker/unitary_checker.py +132 -0
  13. guppylang_internals/compiler/cfg_compiler.py +7 -6
  14. guppylang_internals/compiler/core.py +5 -5
  15. guppylang_internals/compiler/expr_compiler.py +72 -81
  16. guppylang_internals/compiler/modifier_compiler.py +5 -0
  17. guppylang_internals/decorator.py +88 -7
  18. guppylang_internals/definition/custom.py +4 -0
  19. guppylang_internals/definition/declaration.py +6 -2
  20. guppylang_internals/definition/function.py +26 -3
  21. guppylang_internals/definition/metadata.py +87 -0
  22. guppylang_internals/definition/overloaded.py +11 -2
  23. guppylang_internals/definition/pytket_circuits.py +7 -2
  24. guppylang_internals/definition/struct.py +6 -3
  25. guppylang_internals/definition/wasm.py +42 -10
  26. guppylang_internals/diagnostic.py +72 -15
  27. guppylang_internals/engine.py +10 -13
  28. guppylang_internals/nodes.py +55 -24
  29. guppylang_internals/std/_internal/checker.py +13 -108
  30. guppylang_internals/std/_internal/compiler/array.py +37 -2
  31. guppylang_internals/std/_internal/compiler/either.py +14 -2
  32. guppylang_internals/std/_internal/compiler/list.py +1 -1
  33. guppylang_internals/std/_internal/compiler/platform.py +153 -0
  34. guppylang_internals/std/_internal/compiler/prelude.py +12 -4
  35. guppylang_internals/std/_internal/compiler/tket_bool.py +1 -6
  36. guppylang_internals/std/_internal/compiler/tket_exts.py +4 -5
  37. guppylang_internals/std/_internal/debug.py +18 -9
  38. guppylang_internals/std/_internal/util.py +1 -1
  39. guppylang_internals/tracing/object.py +14 -0
  40. guppylang_internals/tys/errors.py +23 -1
  41. guppylang_internals/tys/parsing.py +3 -3
  42. guppylang_internals/tys/printing.py +2 -8
  43. guppylang_internals/tys/qubit.py +37 -2
  44. guppylang_internals/tys/ty.py +60 -64
  45. guppylang_internals/wasm_util.py +129 -0
  46. {guppylang_internals-0.25.0.dist-info → guppylang_internals-0.27.0.dist-info}/METADATA +5 -4
  47. {guppylang_internals-0.25.0.dist-info → guppylang_internals-0.27.0.dist-info}/RECORD +49 -45
  48. {guppylang_internals-0.25.0.dist-info → guppylang_internals-0.27.0.dist-info}/WHEEL +1 -1
  49. {guppylang_internals-0.25.0.dist-info → guppylang_internals-0.27.0.dist-info}/licenses/LICENCE +0 -0
@@ -5,7 +5,7 @@ from guppylang_internals.diagnostic import Error, Help, Note
5
5
 
6
6
  if TYPE_CHECKING:
7
7
  from guppylang_internals.definition.parameter import ParamDef
8
- from guppylang_internals.tys.ty import Type
8
+ from guppylang_internals.tys.ty import Type, UnitaryFlags
9
9
 
10
10
 
11
11
  @dataclass(frozen=True)
@@ -182,3 +182,25 @@ class InvalidFlagError(Error):
182
182
  class FlagNotAllowedError(Error):
183
183
  title: ClassVar[str] = "Invalid annotation"
184
184
  span_label: ClassVar[str] = "`@` type annotations are not allowed in this position"
185
+
186
+
187
+ @dataclass(frozen=True)
188
+ class UnitaryCallError(Error):
189
+ title: ClassVar[str] = "Unitary constraint violation"
190
+ span_label: ClassVar[str] = (
191
+ "This function cannot be called in a {render_flags} context"
192
+ )
193
+ flags: "UnitaryFlags"
194
+
195
+ @property
196
+ def render_flags(self) -> str:
197
+ from guppylang_internals.tys.ty import UnitaryFlags
198
+
199
+ if self.flags == UnitaryFlags.Dagger:
200
+ return "dagger"
201
+ elif self.flags == UnitaryFlags.Control:
202
+ return "control"
203
+ elif self.flags == UnitaryFlags.Power:
204
+ return "power"
205
+ else:
206
+ return "unitary"
@@ -107,7 +107,7 @@ def arg_from_ast(node: AstNode, ctx: TypeParsingCtx) -> Argument:
107
107
  return ConstArg(ConstValue(bool_type(), v))
108
108
  # Integer literals are turned into nat args.
109
109
  # TODO: To support int args, we need proper inference logic here
110
- # See https://github.com/CQCL/guppylang/issues/1030
110
+ # See https://github.com/quantinuum/guppylang/issues/1030
111
111
  case int(v) if v >= 0:
112
112
  nat_ty = NumericType(NumericType.Kind.Nat)
113
113
  return ConstArg(ConstValue(nat_ty, v))
@@ -117,7 +117,7 @@ def arg_from_ast(node: AstNode, ctx: TypeParsingCtx) -> Argument:
117
117
  # String literals are ignored for now since they could also be stringified
118
118
  # types.
119
119
  # TODO: To support string args, we need proper inference logic here
120
- # See https://github.com/CQCL/guppylang/issues/1030
120
+ # See https://github.com/quantinuum/guppylang/issues/1030
121
121
  case str(_):
122
122
  pass
123
123
 
@@ -289,7 +289,7 @@ def check_function_arg(
289
289
  ctx.param_var_mapping[name] = ConstParam(
290
290
  len(ctx.param_var_mapping), name, ty, from_comptime_arg=True
291
291
  )
292
- return FuncInput(ty, flags)
292
+ return FuncInput(ty, flags, name)
293
293
 
294
294
 
295
295
  if sys.version_info >= (3, 12):
@@ -11,7 +11,6 @@ from guppylang_internals.tys.ty import (
11
11
  NumericType,
12
12
  OpaqueType,
13
13
  StructType,
14
- SumType,
15
14
  TupleType,
16
15
  Type,
17
16
  )
@@ -122,11 +121,6 @@ class TypePrinter:
122
121
  args = ", ".join(self._visit(arg, True) for arg in ty.args)
123
122
  return f"({args})"
124
123
 
125
- @_visit.register
126
- def _visit_SumType(self, ty: SumType, inside_row: bool) -> str:
127
- args = ", ".join(self._visit(arg, True) for arg in ty.args)
128
- return f"Sum[{args}]"
129
-
130
124
  @_visit.register
131
125
  def _visit_NoneType(self, ty: NoneType, inside_row: bool) -> str:
132
126
  return "None"
@@ -168,7 +162,7 @@ def signature_to_str(name: str, sig: FunctionType) -> str:
168
162
  assert sig.input_names is not None
169
163
  s = f"def {name}("
170
164
  s += ", ".join(
171
- f"{name}: {inp.ty}{TypePrinter._print_flags(inp.flags)}"
172
- for name, inp in zip(sig.input_names, sig.inputs, strict=True)
165
+ f"{inp.name}: {inp.ty}{TypePrinter._print_flags(inp.flags)}"
166
+ for inp in sig.inputs
173
167
  )
174
168
  return s + ") -> " + str(sig.output)
@@ -1,8 +1,10 @@
1
1
  import functools
2
- from typing import cast
2
+ from typing import Any, cast
3
3
 
4
4
  from guppylang_internals.definition.ty import TypeDef
5
- from guppylang_internals.tys.ty import Type
5
+ from guppylang_internals.tys.arg import TypeArg
6
+ from guppylang_internals.tys.common import Visitor
7
+ from guppylang_internals.tys.ty import OpaqueType, Type
6
8
 
7
9
 
8
10
  @functools.cache
@@ -25,3 +27,36 @@ def is_qubit_ty(ty: Type) -> bool:
25
27
  before qubit types are registered.
26
28
  """
27
29
  return ty == qubit_ty()
30
+
31
+
32
+ class QubitFinder(Visitor):
33
+ """Type visitor that checks if a type contains the qubit type."""
34
+
35
+ class FoundFlag(Exception):
36
+ pass
37
+
38
+ @functools.singledispatchmethod
39
+ def visit(self, ty: Any) -> bool: # type: ignore[override]
40
+ return False
41
+
42
+ @visit.register
43
+ def _visit_OpaqueType(self, ty: OpaqueType) -> bool:
44
+ if is_qubit_ty(ty):
45
+ raise self.FoundFlag
46
+ return False
47
+
48
+ @visit.register
49
+ def _visit_TypeArg(self, arg: TypeArg) -> bool:
50
+ arg.ty.visit(self)
51
+ return True
52
+
53
+
54
+ def contain_qubit_ty(ty: Type) -> bool:
55
+ """Checks if the given type contains the qubit type."""
56
+ finder = QubitFinder()
57
+ try:
58
+ ty.visit(finder)
59
+ except QubitFinder.FoundFlag:
60
+ return True
61
+ else:
62
+ return False
@@ -1,6 +1,6 @@
1
1
  from abc import ABC, abstractmethod
2
2
  from collections.abc import Sequence
3
- from dataclasses import dataclass, field
3
+ from dataclasses import dataclass, field, replace
4
4
  from enum import Enum, Flag, auto
5
5
  from functools import cached_property, total_ordering
6
6
  from typing import TYPE_CHECKING, ClassVar, TypeAlias, cast
@@ -369,6 +369,21 @@ class InputFlags(Flag):
369
369
  Comptime = auto()
370
370
 
371
371
 
372
+ class UnitaryFlags(Flag):
373
+ """Flags that can be set on functions to indicate their unitary properties.
374
+
375
+ The flags indicate under which conditions a function can be used
376
+ in a unitary context.
377
+ """
378
+
379
+ NoFlags = 0
380
+ Control = auto()
381
+ Dagger = auto()
382
+ Power = auto()
383
+
384
+ Unitary = Control | Dagger | Power
385
+
386
+
372
387
  @dataclass(frozen=True)
373
388
  class FuncInput:
374
389
  """A single input of a function type."""
@@ -376,6 +391,10 @@ class FuncInput:
376
391
  ty: "Type"
377
392
  flags: InputFlags
378
393
 
394
+ #: Name of this input, or `None` if it is an unnamed argument (e.g. inside a
395
+ #: `Callable`). We use `compare=False` because names are not visible to the caller.
396
+ name: str | None = field(default=None, compare=False)
397
+
379
398
 
380
399
  @dataclass(frozen=True, init=False)
381
400
  class FunctionType(ParametrizedTypeBase):
@@ -384,7 +403,6 @@ class FunctionType(ParametrizedTypeBase):
384
403
  inputs: Sequence[FuncInput]
385
404
  output: "Type"
386
405
  params: Sequence[Parameter]
387
- input_names: Sequence[str] | None
388
406
  comptime_args: Sequence[ConstArg]
389
407
 
390
408
  args: Sequence[Argument] = field(init=False)
@@ -394,13 +412,15 @@ class FunctionType(ParametrizedTypeBase):
394
412
  intrinsically_droppable: bool = field(default=True, init=True)
395
413
  hugr_bound: ht.TypeBound = field(default=ht.TypeBound.Copyable, init=False)
396
414
 
415
+ unitary_flags: UnitaryFlags = field(default=UnitaryFlags.NoFlags, init=True)
416
+
397
417
  def __init__(
398
418
  self,
399
419
  inputs: Sequence[FuncInput],
400
420
  output: "Type",
401
- input_names: Sequence[str] | None = None,
402
421
  params: Sequence[Parameter] | None = None,
403
422
  comptime_args: Sequence[ConstArg] | None = None,
423
+ unitary_flags: UnitaryFlags = UnitaryFlags.NoFlags,
404
424
  ) -> None:
405
425
  # We need a custom __init__ to set the args
406
426
  args: list[Argument] = [TypeArg(inp.ty) for inp in inputs]
@@ -416,12 +436,19 @@ class FunctionType(ParametrizedTypeBase):
416
436
  ]
417
437
  args += comptime_args
418
438
 
439
+ # Either all inputs must have unique names, or none of them have names
440
+ names = {inp.name for inp in inputs if inp.name is not None}
441
+ if len(names) not in (0, len(inputs)):
442
+ raise InternalGuppyError(
443
+ "Tried to construct FunctionType with invalid input names"
444
+ )
445
+
419
446
  object.__setattr__(self, "args", args)
420
447
  object.__setattr__(self, "comptime_args", comptime_args)
421
448
  object.__setattr__(self, "inputs", inputs)
422
449
  object.__setattr__(self, "output", output)
423
- object.__setattr__(self, "input_names", input_names or [])
424
450
  object.__setattr__(self, "params", params)
451
+ object.__setattr__(self, "unitary_flags", unitary_flags)
425
452
 
426
453
  @property
427
454
  def parametrized(self) -> bool:
@@ -436,6 +463,16 @@ class FunctionType(ParametrizedTypeBase):
436
463
  return set()
437
464
  return super().bound_vars
438
465
 
466
+ @cached_property
467
+ def input_names(self) -> Sequence[str] | None:
468
+ """Names of all inputs or `None` if there are unnamed inputs."""
469
+ names: list[str] = []
470
+ for inp in self.inputs:
471
+ if inp.name is None:
472
+ return None
473
+ names.append(inp.name)
474
+ return names
475
+
439
476
  def cast(self) -> "Type":
440
477
  """Casts an implementor of `TypeBase` into a `Type`."""
441
478
  return self
@@ -494,12 +531,8 @@ class FunctionType(ParametrizedTypeBase):
494
531
  def transform(self, transformer: Transformer) -> "Type":
495
532
  """Accepts a transformer on this type."""
496
533
  return transformer.transform(self) or FunctionType(
497
- [
498
- FuncInput(inp.ty.transform(transformer), inp.flags)
499
- for inp in self.inputs
500
- ],
534
+ [replace(inp, ty=inp.ty.transform(transformer)) for inp in self.inputs],
501
535
  self.output.transform(transformer),
502
- self.input_names,
503
536
  self.params,
504
537
  )
505
538
 
@@ -529,9 +562,8 @@ class FunctionType(ParametrizedTypeBase):
529
562
 
530
563
  inst = Instantiator(full_inst)
531
564
  return FunctionType(
532
- [FuncInput(inp.ty.transform(inst), inp.flags) for inp in self.inputs],
565
+ [replace(inp, ty=inp.ty.transform(inst)) for inp in self.inputs],
533
566
  self.output.transform(inst),
534
- self.input_names,
535
567
  remaining_params,
536
568
  # Comptime type arguments also need to be instantiated
537
569
  comptime_args=[
@@ -548,6 +580,18 @@ class FunctionType(ParametrizedTypeBase):
548
580
  exs = [param.to_existential() for param in self.params]
549
581
  return self.instantiate([arg for arg, _ in exs]), [var for _, var in exs]
550
582
 
583
+ def with_unitary_flags(self, flags: UnitaryFlags) -> "FunctionType":
584
+ """Returns a copy of this function type with the specified unitary flags."""
585
+ # N.B. we can't use `dataclasses.replace` here since `FunctionType` has a custom
586
+ # constructor
587
+ return FunctionType(
588
+ self.inputs,
589
+ self.output,
590
+ self.params,
591
+ self.comptime_args,
592
+ flags,
593
+ )
594
+
551
595
 
552
596
  @dataclass(frozen=True, init=False)
553
597
  class TupleType(ParametrizedTypeBase):
@@ -592,53 +636,6 @@ class TupleType(ParametrizedTypeBase):
592
636
  )
593
637
 
594
638
 
595
- @dataclass(frozen=True, init=False)
596
- class SumType(ParametrizedTypeBase):
597
- """Type of sums.
598
-
599
- Note that this type is only used internally when constructing the Hugr. Users cannot
600
- write down this type.
601
- """
602
-
603
- element_types: Sequence["Type"]
604
-
605
- def __init__(self, element_types: Sequence["Type"]) -> None:
606
- # We need a custom __init__ to set the args
607
- args = [TypeArg(ty) for ty in element_types]
608
- object.__setattr__(self, "args", args)
609
- object.__setattr__(self, "element_types", element_types)
610
-
611
- @property
612
- def intrinsically_copyable(self) -> bool:
613
- """Whether objects of this type can be implicitly copied."""
614
- return True
615
-
616
- @property
617
- def intrinsically_droppable(self) -> bool:
618
- """Whether objects of this type can be dropped."""
619
- return True
620
-
621
- def cast(self) -> "Type":
622
- """Casts an implementor of `TypeBase` into a `Type`."""
623
- return self
624
-
625
- def to_hugr(self, ctx: ToHugrContext) -> ht.Sum:
626
- """Computes the Hugr representation of the type."""
627
- rows = [type_to_row(ty) for ty in self.element_types]
628
- if all(len(row) == 0 for row in rows):
629
- return ht.UnitSum(size=len(rows))
630
- elif len(rows) == 1:
631
- return ht.Tuple(*row_to_hugr(rows[0], ctx))
632
- else:
633
- return ht.Sum(variant_rows=rows_to_hugr(rows, ctx))
634
-
635
- def transform(self, transformer: Transformer) -> "Type":
636
- """Accepts a transformer on this type."""
637
- return transformer.transform(self) or SumType(
638
- [ty.transform(transformer) for ty in self.element_types]
639
- )
640
-
641
-
642
639
  @dataclass(frozen=True)
643
640
  class OpaqueType(ParametrizedTypeBase):
644
641
  """Type that is directly backed by a Hugr opaque type.
@@ -727,9 +724,8 @@ class StructType(ParametrizedTypeBase):
727
724
 
728
725
 
729
726
  #: The type of parametrized Guppy types.
730
- ParametrizedType: TypeAlias = (
731
- FunctionType | TupleType | SumType | OpaqueType | StructType
732
- )
727
+ ParametrizedType: TypeAlias = FunctionType | TupleType | OpaqueType | StructType
728
+
733
729
 
734
730
  #: The type of Guppy types.
735
731
  #:
@@ -811,8 +807,6 @@ def unify(s: Type | Const, t: Type | Const, subst: "Subst | None") -> "Subst | N
811
807
  return _unify_args(s, t, subst)
812
808
  case TupleType() as s, TupleType() as t:
813
809
  return _unify_args(s, t, subst)
814
- case SumType() as s, SumType() as t:
815
- return _unify_args(s, t, subst)
816
810
  case OpaqueType() as s, OpaqueType() as t if s.defn == t.defn:
817
811
  return _unify_args(s, t, subst)
818
812
  case StructType() as s, StructType() as t if s.defn == t.defn:
@@ -881,6 +875,8 @@ def function_tensor_signature(tys: list[FunctionType]) -> FunctionType:
881
875
  outputs: list[Type] = []
882
876
  for fun_ty in tys:
883
877
  assert not fun_ty.parametrized
884
- inputs.extend(fun_ty.inputs)
878
+ # Forget the function input names since they might be non-unique across the
879
+ # tensored functions
880
+ inputs.extend([replace(inp, name=None) for inp in fun_ty.inputs])
885
881
  outputs.extend(type_to_row(fun_ty.output))
886
882
  return FunctionType(inputs, row_to_type(outputs))
@@ -0,0 +1,129 @@
1
+ from dataclasses import dataclass
2
+ from typing import ClassVar
3
+
4
+ import wasmtime as wt
5
+
6
+ from guppylang_internals.diagnostic import Error, Note
7
+ from guppylang_internals.tys.ty import (
8
+ FuncInput,
9
+ FunctionType,
10
+ InputFlags,
11
+ NoneType,
12
+ NumericType,
13
+ Type,
14
+ )
15
+
16
+
17
+ # The thing to be imported elsewhere
18
+ @dataclass
19
+ class ConcreteWasmModule:
20
+ filename: str
21
+ # Function names in order for looking up by index
22
+ functions: list[str]
23
+ function_sigs: dict[str, FunctionType | str]
24
+
25
+
26
+ @dataclass(frozen=True)
27
+ class WasmSignatureError(Error):
28
+ title: ClassVar[str] = (
29
+ "Invalid signature for @wasm function `{fn_name}`\n"
30
+ "in wasm file:\n`{filename}`"
31
+ )
32
+ fn_name: str
33
+ filename: str
34
+
35
+ @dataclass(frozen=True)
36
+ class Message(Note):
37
+ message = "{msg}"
38
+ msg: str
39
+
40
+
41
+ @dataclass(frozen=True)
42
+ class WasmFileNotFound(Error):
43
+ title: ClassVar[str] = "Wasm file `{file}` not found"
44
+ file: str
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class WasmFunctionNotInFile(Error):
49
+ title: ClassVar[str] = (
50
+ "Declared wasm function `{function}` isn't exported by wasm file"
51
+ )
52
+ function: str
53
+
54
+ @dataclass(frozen=True)
55
+ class WasmFileNote(Note):
56
+ message: ClassVar[str] = "Wasm file:\n`{filename}`"
57
+ filename: str
58
+
59
+
60
+ @dataclass(frozen=True)
61
+ class WasmSigMismatchError(Error):
62
+ title: ClassVar[str] = "Wasm signature mismatch"
63
+ span_label: ClassVar[str] = (
64
+ "Signature of wasm function didn't match that in provided wasm file"
65
+ )
66
+
67
+ @dataclass(frozen=True)
68
+ class Declaration(Note):
69
+ message: ClassVar[str] = "Declared signature: {declared}"
70
+ declared: str
71
+
72
+ @dataclass(frozen=True)
73
+ class Actual(Note):
74
+ message: ClassVar[str] = "Signature in wasm: {actual}"
75
+ actual: str
76
+
77
+
78
+ def decode_type(ty: wt.ValType) -> Type | None:
79
+ if ty == wt.ValType.i64():
80
+ return NumericType(NumericType.Kind.Int)
81
+ elif ty == wt.ValType.f64():
82
+ return NumericType(NumericType.Kind.Float)
83
+ else:
84
+ return None
85
+
86
+
87
+ def decode_sig(
88
+ params: list[wt.ValType], output: wt.ValType | None
89
+ ) -> FunctionType | str:
90
+ # Function args in wasm are called "params"
91
+ my_params: list[FuncInput] = []
92
+ for p in params:
93
+ if ty := decode_type(p):
94
+ my_params.append(FuncInput(ty, flags=InputFlags.NoFlags))
95
+ else:
96
+ return f"Unsupported input type: {p}"
97
+ if output:
98
+ if ty := decode_type(output):
99
+ return FunctionType(my_params, ty)
100
+ else:
101
+ return f"Unsupported output type: {output}"
102
+ else:
103
+ return FunctionType(my_params, NoneType())
104
+
105
+
106
+ def decode_wasm_functions(filename: str) -> ConcreteWasmModule:
107
+ engine = wt.Engine()
108
+ mod = wt.Module.from_file(engine, filename)
109
+
110
+ functions: list[str] = []
111
+ function_sigs: dict[str, FunctionType | str] = {}
112
+ for fn in mod.exports:
113
+ functions.append(fn.name)
114
+ match fn.type:
115
+ case wt.FuncType() as fun_ty:
116
+ match fun_ty.results:
117
+ case []:
118
+ data = decode_sig(fun_ty.params, None)
119
+ case [output]:
120
+ data = decode_sig(fun_ty.params, output)
121
+ case _multi:
122
+ data = (
123
+ f"Multiple output types unsupported in function `{fn.name}`"
124
+ )
125
+ case _:
126
+ data = f"`{fn.name}` is not exported as a function"
127
+ function_sigs[fn.name] = data
128
+
129
+ return ConcreteWasmModule(filename, functions, function_sigs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: guppylang-internals
3
- Version: 0.25.0
3
+ Version: 0.27.0
4
4
  Summary: Compiler internals for `guppylang` package.
5
5
  Author-email: Mark Koch <mark.koch@quantinuum.com>, TKET development team <tket-support@quantinuum.com>
6
6
  Maintainer-email: Mark Koch <mark.koch@quantinuum.com>, TKET development team <tket-support@quantinuum.com>
@@ -219,9 +219,10 @@ Classifier: Programming Language :: Python :: 3.13
219
219
  Classifier: Programming Language :: Python :: 3.14
220
220
  Classifier: Topic :: Software Development :: Compilers
221
221
  Requires-Python: <4,>=3.10
222
- Requires-Dist: hugr~=0.14.1
222
+ Requires-Dist: hugr~=0.15.0
223
223
  Requires-Dist: tket-exts~=0.12.0
224
224
  Requires-Dist: typing-extensions<5,>=4.9.0
225
+ Requires-Dist: wasmtime~=v38.0.0
225
226
  Provides-Extra: pytket
226
227
  Requires-Dist: pytket>=1.34; extra == 'pytket'
227
228
  Description-Content-Type: text/markdown
@@ -244,10 +245,10 @@ pip install guppylang-internals
244
245
 
245
246
  See [DEVELOPMENT.md] information on how to develop and contribute to this package.
246
247
 
247
- [DEVELOPMENT.md]: https://github.com/CQCL/guppylang/blob/main/DEVELOPMENT.md
248
+ [DEVELOPMENT.md]: https://github.com/quantinuum/guppylang/blob/main/DEVELOPMENT.md
248
249
 
249
250
  ## License
250
251
 
251
252
  This project is licensed under Apache License, Version 2.0 ([LICENCE][] or http://www.apache.org/licenses/LICENSE-2.0).
252
253
 
253
- [LICENCE]: https://github.com/CQCL/guppylang/blob/main/LICENCE
254
+ [LICENCE]: https://github.com/quantinuum/guppylang/blob/main/LICENCE