Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: angle is now a struct and emitted as a rotation #485

Merged
merged 15 commits into from
Sep 18, 2024
14 changes: 11 additions & 3 deletions execute_llvm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn compile_module_to_string(hugr_json: &str) -> PyResult<String> {
fn run_function<T>(
hugr_json: &str,
fn_name: &str,
parse_result: impl FnOnce(GenericValue) -> PyResult<T>,
parse_result: impl FnOnce(&Context, GenericValue) -> PyResult<T>,
) -> PyResult<T> {
let hugr = parse_hugr(hugr_json)?;
let ctx = Context::create();
Expand All @@ -108,12 +108,12 @@ fn run_function<T>(
.create_execution_engine()
.map_err(|_| pyerr!("Failed to create execution engine"))?;
let llvm_result = unsafe { ee.run_function(fv, &[]) };
parse_result(llvm_result)
parse_result(&ctx, llvm_result)
}

#[pyfunction]
fn run_int_function(hugr_json: &str, fn_name: &str) -> PyResult<i64> {
run_function::<i64>(hugr_json, fn_name, |llvm_val| {
run_function::<i64>(hugr_json, fn_name, |_, llvm_val| {
// GenericVal is 64 bits wide
let int_with_sign = llvm_val.as_int(true);
let unsigned_int =
Expand All @@ -123,9 +123,17 @@ fn run_int_function(hugr_json: &str, fn_name: &str) -> PyResult<i64> {
})
}

#[pyfunction]
fn run_float_function(hugr_json: &str, fn_name: &str) -> PyResult<f64> {
run_function::<f64>(hugr_json, fn_name, |ctx, llvm_val| {
Ok(llvm_val.as_float(&ctx.f64_type()))
})
}

#[pymodule]
fn execute_llvm(_py: Python, m: &PyModule) -> PyResult<()> {
m.add_function(wrap_pyfunction!(compile_module_to_string, m)?)?;
m.add_function(wrap_pyfunction!(run_int_function, m)?)?;
m.add_function(wrap_pyfunction!(run_float_function, m)?)?;
Ok(())
}
15 changes: 3 additions & 12 deletions guppylang/module.py
Original file line number Diff line number Diff line change
Expand Up @@ -336,19 +336,10 @@ def compile(self) -> Package:
# TODO: Currently we just include a hardcoded list of extensions. We should
# compute this dynamically from the imported dependencies instead.
#
# The hugr prelude extensions are implicit.
from guppylang.prelude._internal.compiler.quantum import (
HSERIES_EXTENSION,
QUANTUM_EXTENSION,
RESULT_EXTENSION,
)
# The hugr prelude and std_extensions are implicit.
from guppylang.prelude._internal.compiler.quantum import TKET2_EXTENSIONS

extensions = [
guppylang.compiler.hugr_extension.EXTENSION,
QUANTUM_EXTENSION,
HSERIES_EXTENSION,
RESULT_EXTENSION,
]
extensions = [*TKET2_EXTENSIONS, guppylang.compiler.hugr_extension.EXTENSION]

package = Package(modules=[hugr], extensions=extensions)
self._compiled = True
Expand Down
57 changes: 0 additions & 57 deletions guppylang/prelude/_internal/compiler/angle.py

This file was deleted.

45 changes: 43 additions & 2 deletions guppylang/prelude/_internal/compiler/quantum.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@

from __future__ import annotations

from hugr import Wire
from hugr import Wire, ops
from hugr import tys as ht
from hugr.std.float import FLOAT_T

from guppylang.definition.custom import CustomInoutCallCompiler
from guppylang.definition.value import CallReturnWires
from guppylang.prelude._internal.compiler.prelude import build_error, build_panic
from guppylang.prelude._internal.json_defs import load_extension

# ----------------------------------------------
Expand All @@ -19,17 +21,26 @@
HSERIES_EXTENSION = load_extension("tket2.hseries")
QUANTUM_EXTENSION = load_extension("tket2.quantum")
RESULT_EXTENSION = load_extension("tket2.result")
ROTATION_EXTENSION = load_extension("tket2.rotation")

ROTATION_T_DEF = ROTATION_EXTENSION.get_type("rotation")
ROTATION_T = ht.ExtType(ROTATION_T_DEF)

TKET2_EXTENSIONS = [
FUTURES_EXTENSION,
HSERIES_EXTENSION,
QUANTUM_EXTENSION,
RESULT_EXTENSION,
ROTATION_EXTENSION,
]


ANGLE_T = QUANTUM_EXTENSION.get_type("angle")
def from_halfturns() -> ops.ExtOp:
return ops.ExtOp(
ROTATION_EXTENSION.get_op("from_halfturns"),
ht.FunctionType([FLOAT_T], [ht.Sum([[], [ROTATION_T]])]),
)


# ------------------------------------------------------
# --------- Custom compilers for non-native ops --------
Expand All @@ -48,3 +59,33 @@ def compile_with_inouts(self, args: list[Wire]) -> CallReturnWires:
q,
)
return CallReturnWires(regular_returns=[bit], inout_returns=[q])


class RotationCompiler(CustomInoutCallCompiler):
opname: str

def __init__(self, opname: str):
self.opname = opname

def compile_with_inouts(self, args: list[Wire]) -> CallReturnWires:
from guppylang.prelude._internal.util import quantum_op

[q, angle] = args
[halfturns] = self.builder.add_op(ops.UnpackTuple([FLOAT_T]), angle)
[mb_rotation] = self.builder.add_op(from_halfturns(), halfturns)

conditional = self.builder.add_conditional(mb_rotation)
with conditional.add_case(0) as case:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really for this PR, but somewhere in guppy we should have a build_unwrap helper that does this faffing with a conditional two cases, a passthrough and a panic...

error = build_error(case, 1, "Non-finite number of half-turns")
case.set_outputs(build_panic(case, [], [ROTATION_T], error))
with conditional.add_case(1) as case:
case.set_outputs(*case.inputs())

q = self.builder.add_op(
quantum_op(self.opname)(
ht.FunctionType([ht.Qubit, ROTATION_T], [ht.Qubit]), []
),
q,
conditional,
)
return CallReturnWires(regular_returns=[], inout_returns=[q])
6 changes: 5 additions & 1 deletion guppylang/prelude/_internal/json_defs/tket2/hseries.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
{
"version": "0.1.0",
"name": "tket2.hseries",
"extension_reqs": [],
"extension_reqs": [
"arithmetic.float.types",
"prelude",
"tket2.futures"
],
"types": {},
"values": {},
"operations": {
Expand Down
Loading
Loading