"""Definition objects that are being exposed to users.These are the objects returned by the `@guppy` decorator. They should not be confusedwith the compiler-internal definition objects in the `definitions` module."""importastfromcollections.abcimportSequencefromdataclassesimportdataclassfromtypingimportAny,ClassVar,Generic,ParamSpec,TypeVar,castimportguppylang_internalsfromguppylang_internals.definition.valueimportCompiledCallableDeffromguppylang_internals.diagnosticimportError,Notefromguppylang_internals.engineimportENGINE,CoreMetadataKeysfromguppylang_internals.errorimportGuppyErrorfromguppylang_internals.spanimportSpan,to_spanfromguppylang_internals.tracing.objectimportTracingDefMixinfromguppylang_internals.tracing.utilimporthide_tracefromhugr.hugrimportHugrfromhugr.packageimportPackageimportguppylangfromguppylang.emulatorimportEmulatorBuilder,EmulatorInstance__all__=("GuppyDefinition","GuppyFunctionDefinition","GuppyTypeVarDefinition")P=ParamSpec("P")Out=TypeVar("Out")def_update_generator_metadata(hugr:Hugr[Any])->None:"""Update the generator metadata of a Hugr to be guppylang rather than just internals."""key=CoreMetadataKeys.GENERATOR.valuehugr.module_root.metadata[key]={"name":f"guppylang (guppylang-internals-v{guppylang_internals.__version__})","version":guppylang.__version__,}
[docs]@dataclass(frozen=True)classEntrypointArgsError(Error):title:ClassVar[str]="Entrypoint function has arguments"span_label:ClassVar[str]=("Entrypoint function must have no input parameters, found ({input_names}).")args:Sequence[str]@dataclass(frozen=True)classAlternateHint(Note):message:ClassVar[str]=("If the function is not an execution entrypoint,"" consider using `{function_name}.compile_function()`")function_name:str@propertydefinput_names(self)->str:"""Returns a comma-separated list of input names."""return", ".join(f"`{x}`"forxinself.args)
[docs]@dataclass(frozen=True)classGuppyDefinition(TracingDefMixin):"""A general Guppy definition."""
[docs]defcompile(self)->Package:"""Compile a Guppy definition to HUGR."""package:Package=ENGINE.compile(self.id).packageformodinpackage.modules:_update_generator_metadata(mod)returnpackage
[docs]defcheck(self)->None:"""Type-check a Guppy definition."""returnENGINE.check(self.id)
[docs]@dataclass(frozen=True)classGuppyFunctionDefinition(GuppyDefinition,Generic[P,Out]):"""A Guppy function definition."""
[docs]defemulator(self,n_qubits:int,builder:EmulatorBuilder|None=None)->EmulatorInstance:"""Compile this function for emulation with the selene-sim emulator. Calls `compile()` to get the HUGR package and then builds it using the provided `EmulatorBuilder` configuration or a default one. See :py:mod:`guppylang.emulator` for more details on the emulator. Args: n_qubits: The number of qubits to allocate for the function. builder: An optional `EmulatorBuilder` to use for building the emulator instance. If not provided, the default `EmulatorBuilder` will be used. Returns: An `EmulatorInstance` that can be used to run the function in an emulator. """mod=self.compile()builder=builderorEmulatorBuilder()returnbuilder.build(mod,n_qubits=n_qubits)
[docs]defcompile(self)->Package:""" Compiles an execution entrypoint function definition to a HUGR package Equivalent to :py:meth:`GuppyDefinition.compile_entrypoint`. Returns: Package: The compiled package object. Raises: GuppyError: If the entrypoint has arguments. """returnself.compile_entrypoint()
[docs]defcompile_entrypoint(self)->Package:""" Compiles an execution entrypoint function definition to a HUGR package Returns: Package: The compiled package object. Raises: GuppyError: If the entrypoint has arguments. """pack=self.compile_function()# entrypoint cannot be polymorphicmonomorphized_id=(self.id,())compiled_def=ENGINE.compiled.get(monomorphized_id)if(isinstance(compiled_def,CompiledCallableDef)andlen(compiled_def.ty.inputs)>0):# Check if the entrypoint has argumentsdefined_at=cast(ast.FunctionDef,compiled_def.defined_at)start=to_span(defined_at.args.args[0])end=to_span(defined_at.args.args[-1])span=Span(start=start.start,end=end.end)raiseGuppyError(EntrypointArgsError(span=span,args=compiled_def.ty.input_namesor"",).add_sub_diagnostic(EntrypointArgsError.AlternateHint(None,function_name=defined_at.name)))returnpack
[docs]defcompile_function(self)->Package:"""Compile a Guppy function definition to HUGR. Returns: Package: The compiled package object. """returnsuper().compile()
[docs]@dataclass(frozen=True)classGuppyTypeVarDefinition(GuppyDefinition):"""Definition of a Guppy type variable."""# For type variables, we need a `GuppyDefinition` subclass that answers 'yes' to an# instance check on `typing.TypeVar`. This hack is needed since `typing.Generic[T]`# has a runtime check that enforces that the passed `T` is actually a `TypeVar`.__class__:ClassVar[type]=TypeVar_ty_var:TypeVar
[docs]def__eq__(self,other:object)->bool:# We need to compare as equal to an equivalent regular type varifisinstance(other,TypeVar):returnself._ty_var==otherreturnobject.__eq__(self,other)
[docs]def__getattr__(self,name:str)->Any:# Pretend to be a `TypeVar` by providing all of its attributesifhasattr(self._ty_var,name):returngetattr(self._ty_var,name)returnobject.__getattribute__(self,name)